summaryrefslogtreecommitdiff
path: root/xlib-tutorial/2nd-program-anatomy.html
diff options
context:
space:
mode:
authornasr <nsrddyn@gmail.com>2026-01-28 13:13:40 +0100
committernasr <nsrddyn@gmail.com>2026-01-28 13:13:40 +0100
commit3913d1778318cd0c6bfb871148d38abb33ec7fd3 (patch)
tree917728adbf32c877ad591ad9d42f727cc7540b9b /xlib-tutorial/2nd-program-anatomy.html
parent7dead79e05e03a71a502ca4e75d05d126ff9f25c (diff)
checkpoint
Diffstat (limited to 'xlib-tutorial/2nd-program-anatomy.html')
-rw-r--r--xlib-tutorial/2nd-program-anatomy.html282
1 files changed, 282 insertions, 0 deletions
diff --git a/xlib-tutorial/2nd-program-anatomy.html b/xlib-tutorial/2nd-program-anatomy.html
new file mode 100644
index 0000000..d156f7a
--- /dev/null
+++ b/xlib-tutorial/2nd-program-anatomy.html
@@ -0,0 +1,282 @@
1<HTML>
2<HEAD>
3<TITLE>Xlib programming tutorial: anatomy of the most basic Xlib program</TITLE>
4</HEAD>
5
6<BODY>
7<H1 ALIGN=center>Anatomy of the most basic Xlib program</H1>
8
9The program starts with the legal stuff:
10
11<PRE><CODE>
12#include &lt;X11/Xlib.h&gt; // Every Xlib program must include this
13#include &lt;assert.h&gt; // I include this to test return values the lazy way
14#include &lt;unistd.h&gt; // So we got the profile for 10 seconds
15
16#define NIL (0) // A name for the void pointer
17</PRE></CODE>
18
19Then the serious thing. First we open a connection to the server.
20
21<PRE><CODE>
22Display *dpy = XOpenDisplay(NIL);
23assert(dpy);
24</PRE></CODE>
25
26If it fails (and it may), <B><A HREF="/gui/x/xlib/display/opening.html">XOpenDisplay()</A></B> will return NIL.
27
28<P>
29
30We gonna create a window, but we need to get the window's background
31color first. X uses a quite complex color model in order to accommodate
32to every conceivable piece of hardware. Each color is encoded by an integer,
33but the integer for a given color may change from a machine to another
34one, and even on the same machine, from an execution of the program to
35the next. The only "colors" that X guarantees to exist are black and
36white. We can get them using the
37<B><A HREF="/gui/x/xlib/display/display-macros.html#BlackPixel">BlackPixel()</A></B>
38and
39<B><A HREF="/gui/x/xlib/display/display-macros.html#WhitePixel">WhitePixel()</A></B>
40macros.
41
42<PRE><CODE>
43 int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
44 int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));
45</PRE></CODE>
46
47As we yet can see, most of the Xlib calls take the "display" (the
48value returned by
49<B><A HREF="/gui/x/xlib/display/opening.html">XOpenDisplay()</A></B>)
50as their first parameter. <A HREF="server.html">You want to know why ?</A>
51
52<P>
53
54There is still someting magic, (the
55<B><A HREF="/gui/x/xlib/display/display-macros.html#DefaultScreen">DefaultScreen()</A></B>
56stuff), but we gonna keep it for a <A HREF="screen-and-root-window.html">later
57explanation</A>. We now can
58create our window:
59
60<PRE><CODE>
61 // Create the window
62
63 Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
64 200, 100, 0, blackColor, blackColor);
65</PRE></CODE>
66
67Unlike what appears in the <A HREF="./">dialog</A>, we use the
68function
69<B><A HREF="/gui/x/xlib/window/XCreateWindow.html">XCreateSimpleWindow()</A></B>
70instead of
71<B><A HREF="/gui/x/xlib/window/XCreateWindow.html">XCreateWindow()</A></B>.
72<B><A HREF="/gui/x/xlib/window/XCreateWindow.html">XCreateSimpleWindow()</A></B>
73is not really simpler than
74<B><A HREF="/gui/x/xlib/window/XCreateWindow.html">XCreateWindow()</A></B>
75(it takes only a few less parameters), but it uses less concepts, so
76we gonna stick to it for now. There are still a bunch of parameters to
77explain:
78
79<UL>
80
81<LI> <CODE>dpy</CODE> is the usual display connection (<A HREF="server.html">remember</A>).
82
83<P><LI> <CODE>DefaultRootWindow(dpy)</CODE>: yet another parameter that may
84seem magic until now. This is the "parent window" of the window we are
85creating. The window we create appears inside its parent, and is
86bounded by it (the window is said to be "clipped" by its
87parent). Those who guess from the name "Default" that they may be
88other root windows guess right. More on this <A
89HREF="screen-and-root-window.html">later</A>. For now, the default
90root window makes appear our window on the screen, and will give the
91<A HREF="window-manager.html">window manager</A> a chance to decorate
92our window.
93
94<P><LI> <CODE>0, 0</CODE> These are the coordinates of the upper left
95corner of the window (the origin of the coordinates in X is at the
96upper left, contrary to most mathematical textbooks). The dimensions,
97like every dimensions in X, are in pixels (X does not support
98user-defined scales, unlike some other graphical systems like
99<A HREF="/web-directory/science-and-technology/computer/graphics/">OpenGL</A>).
100
101<P>
102
103Contrary to what may seem, there is very little chance for the window
104to appear, at 0,0. The reason is that the
105<A HREF="window-manager.html">window manager</A> will put the window
106at its policy-defined position.
107
108<P><LI> <CODE>200, 100</CODE>: these are the width and height of the
109window, in pixels.
110
111<P><LI> <CODE>0</CODE>: this is the width of the window's border. This
112has nothing to do with the border appended by the
113<A HREF="window-manager.html">window manager</A>, so this is most
114often set to zero.
115
116<P><LI> <CODE>blackColor, blackColor</CODE>: these are the colors of the
117window's border (NOT the
118<A HREF="window-manager.html">window manager</A>'s border), and the
119window's background, respectively.
120<B><A HREF="/gui/x/xlib/window/XCreateWindow.html">XCreateSimpleWindow()</A></B>
121clears the window when created,
122<B><A HREF="/gui/x/xlib/window/XCreateWindow.html">XCreateWindow()</A></B>
123does not.
124
125</UL>
126
127<PRE><CODE>
128 // We want to get MapNotify events
129
130 XSelectInput(dpy, w, StructureNotifyMask);
131</PRE></CODE>
132
133As we're starting to know, X is based upon a
134<A HREF="server.html">client-server</A> architecture. The X server
135sends events to the client (the program we're writing), to keep it
136informed of the modifications in the server. There are many of them
137(each time a window is created, moved, masked, unmasked, and many
138other things), so a client must tell the server the events it is
139interested in. With this <B>XSelectInput()</B> stuff, we tell the
140server we want to be informed of "structural" changes occuring on the
141<TT>w</TT> window. Creation and mapping are such changes. There is no
142way to be informed for example of only mapping modification, and not
143creations, so we've to take everything. In this particular application
144we're interesting in "mapping" events (<I>grosso modo</I>, the window
145appears on the screen).
146
147<PRE><CODE>
148 // "Map" the window (that is, make it appear on the screen)
149
150 XMapWindow(dpy, w);
151</PRE></CODE>
152
153And (once again) this is a <A HREF="server.html">client-server</A>
154system. The map request is asynchronous, meaning that the time this
155instruction is executed doesn't tell us when the window is actually
156mapped. To be sure, we've to wait for the server to send us a
157<B><A HREF="/gui/x/xlib/events/window-state-change/map.html">MapNotify</A></B>
158event (this is why we want to be sensitive to such events).
159
160<PRE><CODE>
161 // Create a "Graphics Context"
162
163 GC gc = XCreateGC(dpy, w, 0, NIL);
164</PRE></CODE>
165
166Yet another magic stuff. But mastering them is the reason of the
167existence of this tutorial...
168
169<P>
170
171For several reasons, the graphical model of X is stateless, meaning
172that the server doesn't remember (among other things) attributes such
173as the drawing color, the thickness of the lines and so on. Thus,
174we've to give <EM>all these parameters</EM> to the server on each
175drawing request. To avoid passing two dozens of parameters, many of
176them unchanged from one request to the next, X uses an object called
177the <B>Graphics Context</B>, or <B>GC</B> for short. We store in the
178graphics context all the needed parameters. Here, we want the color
179used to draw lines, called the foregound color:
180
181<PRE><CODE>
182 // Tell the GC we draw using the white color
183
184 XSetForeground(dpy, gc, whiteColor);
185</PRE></CODE>
186
187There are many other parameters used to draw a line, but all of them
188have reasonable default values.
189
190<P>
191
192That's okay for now. Everything is set up, and we wait for the window
193mapping.
194
195<PRE><CODE>
196 // Wait for the MapNotify event
197
198 for(;;) {
199 XEvent e;
200 XNextEvent(dpy, &e);
201 if (e.type == MapNotify)
202 break;
203 }
204</PRE></CODE>
205
206We loop, taking events as they come and discarding them. When we get a
207<B>MapNotify</B>, we exit the loop. We may get events other than
208<B>MapNotify</B> for two reasons:
209
210<UL>
211<LI> We have selected <B>StructureNotifyMask</B> to get
212<B>MapNotify</B> events, but we could get other events as well (such
213as <B>ConfigureNotify</B>, telling the window has changed in position, and/or
214size).
215<LI> Some events can be received, even if we don't have asked for
216them, they are called "non-maskable". <B>GraphicsExpose</B> is such an
217event.
218</UL>
219
220The non-maskable events are sent only in response to some program
221requests (such as copying an area), so they aren't likely to happen in
222our context.
223
224<P>
225
226The
227<B><A HREF="/gui/x/xlib/event-handling/manipulating-event-queue/XNextEvent.html">XNextEvent()</A></B>
228procedure is blocking, so if there are no event to read, the program
229just wait inside the
230<B><A HREF="/gui/x/xlib/event-handling/manipulating-event-queue/XNextEvent.html">XNextEvent()</A></B>.
231
232<P>
233
234When we have exited the loop, we have good confidence that the window
235appears on the screen. Actually, this may not be the case since, for
236example, the user may have iconified it using the
237<A HREF="window-manager.html">window manager</A>, but for now, we assume the window
238actually appears. We can draw our line:
239
240<PRE><CODE>
241 // Draw the line
242
243 XDrawLine(dpy, w, gc, 10, 60, 180, 20);
244</PRE></CODE>
245
246The line is between points (10, 60) and (180, 20). The (0,0) is at the
247upper left corner of the window, as usual. If the program just
248<TT>sleep</TT>s here, nothing will happen, because, in case you don't
249know, X has a <A HREF="server.html">client-server</A>
250architecture. Thus the request stays in the client, unless we tell it
251to go to the server. This is done by <B><A
252HREF="/gui/x/xlib/event-handling/XFlush.html">XFlush()</A></B>:
253
254<PRE><CODE>
255 // Send the "DrawLine" request to the server
256
257 XFlush(dpy);
258</PRE></CODE>
259
260Clever readers may have noticed that we didn't use
261<B><A HREF="/gui/x/xlib/event-handling/XFlush.html">XFlush()</A></B>
262before, and it didn't prevent all the requests such as
263<B><A HREF="/gui/x/xlib/window/XMapWindow.html">XMapWindow()</A></B>
264to be sent to the server. The answer is that
265<B><A HREF="/gui/x/xlib/event-handling/manipulating-event-queue/XNextEvent.html">XNextEvent()</A></B>
266performs an implicit
267<B><A HREF="/gui/x/xlib/event-handling/XFlush.html">XFlush()</A></B>
268before trying to read some events. We have our line now, we just wait
269for 10 seconds, so we can make people see how beautiful is our work:
270
271<PRE><CODE>
272 // Wait for 10 seconds
273
274 sleep(10);
275</PRE></CODE>
276
277That's all for now. In <!A HREF="more-interaction.html"><B>next
278lesson</B></A>, we will have a (very) little more interaction. [to be continued]
279
280<HR><ADDRESS><A HREF="http://tronche.com/">Christophe Tronche</A>, <A HREF="mailto:ch.tronche@computer.org">ch.tronche@computer.org</A></ADDRESS>
281</BODY>
282</HTML>