From 6659c8c63b82329468b249cc99181d72ec26c698 Mon Sep 17 00:00:00 2001
From: TORRI Vincent
This tutorial is based on the
Xlib Tutorial
@@ -193,37 +194,37 @@
Window System protocol for many years now. It is an
excellent piece of work, but there are applications for which it
is not ideal, for example
+
For these reasons, among others, XCB, an X C binding, has been
designed to solve the above problems and thus provide a base for
+
The X Window System was developed with one major goal:
flexibility. The idea was that the way things look is one thing,
@@ -261,7 +262,7 @@
using shared memory, or using Unix domain sockets (a method for
creating a logical channel on a Unix system between two processes).
Unlike conventional computer programs, that carry some serial
nature, a GUI program usually uses an asynchronous programming
@@ -286,23 +287,23 @@
So the way a GUI program looks is something like that:
+
XCB has been created to eliminate the needs of
programs to actually implement the X protocol layer. This
@@ -313,21 +314,21 @@
the basic XCB notions. They will be detailed later.
- The major notion of using XCB is the X Connection. This is a
- structure representing the connection we have open with a
- given X server. It hides a queue of messages coming from the
- server, and a queue of pending requests that our client
- intends to send to the server. In XCB, this structure is named
- 'XCBConnection'. When we open a connection to an X server, the
- library returns a pointer to such a structure. Later, we
- supply this pointer to any XCB function that should send
- messages to the X server or receive messages from this server.
-
+ The major notion of using XCB is the X Connection. This is a
+ structure representing the connection we have open with a
+ given X server. It hides a queue of messages coming from the
+ server, and a queue of pending requests that our client
+ intends to send to the server. In XCB, this structure is named
+ 'XCBConnection'. When we open a connection to an X server, the
+ library returns a pointer to such a structure. Later, we
+ supply this pointer to any XCB function that should send
+ messages to the X server or receive messages from this server.
+
+ replies: the Xlib killers
+
To ask informations to the X server, we have to make a request
and ask for a reply. With Xlib, these two tasks are
automatically done: Xlib locks the system, sends a request,
@@ -339,14 +340,14 @@
requests/replies with Xlib, with a round-trip latency
T_round_trip that is 5 times long as the time required
to write or read a request/reply (T_write/T_read):
-
The total time is N * (T_write + T_round_trip + T_read).
@@ -362,7 +363,7 @@
when we need them. Here is the time-line for 4
requests/replies when we use this property of XCB:
@@ -391,7 +392,7 @@ get_time(void)
{
struct timeval timev;
- gettimeofday(&timev, NULL);
+ gettimeofday(&timev, NULL);
return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
}
@@ -499,80 +500,80 @@ main ()
return 1;
}
- When we perform various drawing operations (graphics, text,
- etc), we may specify various options for controlling how the
- data will be drawn (what foreground and background colors to
- use, how line edges will be connected, what font to use when
- drawing some text, etc). In order to avoid the need to supply
- hundreds of parameters to each drawing function, a graphical
- context structure is used. We set the various drawing options
- in this structure, and then we pass a pointer to this
- structure to any drawing routines. This is rather handy, as we
- often need to perform several drawing requests with the same
- options. Thus, we would initialize a graphical context, set
- the desired options, and pass this structure to all drawing
- functions.
-
+ When we perform various drawing operations (graphics, text,
+ etc), we may specify various options for controlling how the
+ data will be drawn (what foreground and background colors to
+ use, how line edges will be connected, what font to use when
+ drawing some text, etc). In order to avoid the need to supply
+ hundreds of parameters to each drawing function, a graphical
+ context structure is used. We set the various drawing options
+ in this structure, and then we pass a pointer to this
+ structure to any drawing routines. This is rather handy, as we
+ often need to perform several drawing requests with the same
+ options. Thus, we would initialize a graphical context, set
+ the desired options, and pass this structure to all drawing
+ functions.
+
Note that graphic contexts have no client-side structure in
XCB, they're just XIDs. Xlib has a client-side structure
because it caches the GC contents so it can avoid making
redundant requests, but of course XCB doesn't do that.
- A structure is used to pass events received from the X
- server. XCB supports exactly the events specified in the
- protocol (33 events). This structure contains the type
- of event received, as well as the data associated with the
- event (e.g. position on the screen where the event was
- generated, mouse button associated with the event, region of
- the screen associated with a "redraw" event, etc). The way to
- read the event's data epends on the event type.
-
+ A structure is used to pass events received from the X
+ server. XCB supports exactly the events specified in the
+ protocol (33 events). This structure contains the type
+ of event received, as well as the data associated with the
+ event (e.g. position on the screen where the event was
+ generated, mouse button associated with the event, region of
+ the screen associated with a "redraw" event, etc). The way to
+ read the event's data epends on the event type.
+
- To build XCB from source, you need to have installed at
- least:
-
- You have to checkout in CVS the following modules:
-
- Note that Xproto and xcb-proto exist only to install header
- files, so typing 'make' or 'make all' will produce the message
- "Nothing to be done for 'all'". That's normal.
-
- Compiling XCB-based programs requires linking them with the XCB
- library. This is easily done thanks to pkgconfig:
-
+ To build XCB from source, you need to have installed at
+ least:
+
+ You have to checkout in CVS the following modules:
+
+ Note that Xproto and xcb-proto exist only to install header
+ files, so typing 'make' or 'make all' will produce the message
+ "Nothing to be done for 'all'". That's normal.
+
+ Compiling XCB-based programs requires linking them with the XCB
+ library. This is easily done thanks to pkgconfig:
+
An X program first needs to open the connection to the X
server. There is a function that opens a connection. It requires
@@ -610,32 +611,32 @@ void XCBDisconnect (XCBConnection *c);
Once we opened a connection to an X server, we should check some
basic informations about it: what screens it has, what is the
@@ -688,11 +689,11 @@ main (int argc, char *argv[])
XCBSCREENIter iter;
/* Open the connection to the X server. Use the DISPLAY environment variable */
- c = XCBConnect (NULL, &screen_nbr);
+ c = XCBConnect (NULL, &screen_nbr);
/* Get the screen #screen_nbr */
iter = XCBConnSetupSuccessRepRootsIter (XCBGetSetup (c));
- for (; iter.rem; --screen_nbr, XCBSCREENNext (&iter))
+ for (; iter.rem; --screen_nbr, XCBSCREENNext (&iter))
if (screen_nbr == 0)
{
screen = iter.data;
@@ -710,7 +711,7 @@ main (int argc, char *argv[])
return 1;
}
-
After we got some basic informations about our screen, we can
create our first window. In the X Window System, a window is
@@ -734,16 +735,16 @@ XCBWINDOW XCBWINDOWNew(XCBConnection *c);
XCBVoidCookie XCBCreateWindow (XCBConnection *c, /* Pointer to the XCBConnection structure */
CARD8 depth, /* Depth of the screen */
XCBWINDOW wid, /* Id of the window */
- XCBWINDOW parent, /* Id of an existing window that should be the parent of the new window */
- INT16 x, /* X position of the top-left corner of the window (in pixels) */
- INT16 y, /* Y position of the top-left corner of the window (in pixels) */
- CARD16 width, /* Width of the window (in pixels) */
- CARD16 height, /* Height of the window (in pixels) */
- CARD16 border_width, /* Width of the window's border (in pixels) */
- CARD16 _class,
- XCBVISUALID visual,
- CARD32 value_mask,
- const CARD32 *value_list);
+ XCBWINDOW parent, /* Id of an existing window that should be the parent of the new window */
+ INT16 x, /* X position of the top-left corner of the window (in pixels) */
+ INT16 y, /* Y position of the top-left corner of the window (in pixels) */
+ CARD16 width, /* Width of the window (in pixels) */
+ CARD16 height, /* Height of the window (in pixels) */
+ CARD16 border_width, /* Width of the window's border (in pixels) */
+ CARD16 _class,
+ XCBVISUALID visual,
+ CARD32 value_mask,
+ const CARD32 *value_list);
The fact that we created the window does not mean that it will
@@ -782,15 +783,15 @@ main (int argc, char *argv[])
/* Create the window */
XCBCreateWindow (c, /* Connection */
- 0, /* depth */
- win.window, /* window Id */
- screen->root, /* parent window */
- 0, 0, /* x, y */
- 150, 150, /* width, height */
- 10, /* border_width */
- InputOutput, /* class */
- screen->root_visual, /* visual */
- 0, NULL); /* masks, not used yet */
+ 0, /* depth */
+ win.window, /* window Id */
+ screen->root, /* parent window */
+ 0, 0, /* x, y */
+ 150, 150, /* width, height */
+ 10, /* border_width */
+ InputOutput, /* class */
+ screen->root_visual, /* visual */
+ 0, NULL); /* masks, not used yet */
/* Map the window on the screen */
XCBMapWindow (c, win.window);
@@ -845,22 +846,22 @@ int XCBSync(XCBConnection *c, XCBGenericError **e);
Drawing in a window can be done using various graphical
functions (drawing pixels, lines, rectangles, etc). In order to
@@ -869,42 +870,42 @@ int XCBSync(XCBConnection *c, XCBGenericError **e);
with, etc). This is done using a graphical context.
- As we said, a graphical context defines several attributes to
- be used with the various drawing functions. For this, we
- define a graphical context. We can use more than one graphical
- context with a single window, in order to draw in multiple
- styles (different colors, different line widths, etc). In XCB,
- a Graphics Context is, as a window, characterized by an Id:
+ As we said, a graphical context defines several attributes to
+ be used with the various drawing functions. For this, we
+ define a graphical context. We can use more than one graphical
+ context with a single window, in order to draw in multiple
+ styles (different colors, different line widths, etc). In XCB,
+ a Graphics Context is, as a window, characterized by an Id:
We first ask the X server to attribute an Id to our graphic
- context with this function:
+ context with this function:
Then, we set the attributes of the graphic context with this function:
- We give now an example on how to allocate a graphic context
- that specifies that each drawing functions that use it will
- draw in foreground with a black color.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
+
+
+
-
-
-
+
+
W-----RW-----RW-----RW-----R
-
+
-
WWWW--RRRR
+
-
-
-
-
+
+
+
gcc -Wall prog.c -o prog `pkg-config --cflags --libs xcb`
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
-
+
typedef struct {
CARD32 xid;
} XCBGCONTEXT;
+
XCBGCONTEXT XCBGCONTEXTNew (XCBConnection *c);
+
XCBVoidCookie XCBCreateGC (XCBConnection *c,
XCBGCONTEXT cid,
- XCBDRAWABLE drawable,
- CARD32 value_mask,
- const CARD32 *value_list);
+ XCBDRAWABLE drawable,
+ CARD32 value_mask,
+ const CARD32 *value_list);
#include <X11/XCB/xcb.h> @@ -934,171 +935,171 @@ main (int argc, char *argv[])
Note should be taken regarding the role of "value_mask" and - "value_list" in the prototype of XCBCreateGC(). Since a - graphic context has many attributes, and since we often just - want to define a few of them, we need to be able to tell the - XCBCreateGC() which attributes we - want to set. This is what the "value_mask" parameter is - for. We then use the "value_list" parameter to specify actual - values for the attribute we defined in "value_mask". Thus, for - each constant used in "value_list", we will use the matching - constant in "value_mask". In this case, we define a graphic - context with one attribute: when drawing (a point, a line, - etc), the foreground color will be black. The rest of the - attributes of this graphic context will be set to their - default values. -
-- See the next Subsection for more details. -
+ "value_list" in the prototype of XCBCreateGC(). Since a + graphic context has many attributes, and since we often just + want to define a few of them, we need to be able to tell the + XCBCreateGC() which attributes we + want to set. This is what the "value_mask" parameter is + for. We then use the "value_list" parameter to specify actual + values for the attribute we defined in "value_mask". Thus, for + each constant used in "value_list", we will use the matching + constant in "value_mask". In this case, we define a graphic + context with one attribute: when drawing (a point, a line, + etc), the foreground color will be black. The rest of the + attributes of this graphic context will be set to their + default values. + ++ See the next Subsection for more details. +
- Once we have allocated a Graphic Context, we may need to - change its attributes (for example, changing the foreground - color we use to draw a line, or changing the attributes of the - font we use to display strings. See Subsections Drawing with a - color and Assigning a Font to a Graphic Context). This is done - by using this function: -
-+
+
+ Once we have allocated a Graphic Context, we may need to + change its attributes (for example, changing the foreground + color we use to draw a line, or changing the attributes of the + font we use to display strings. See Subsections Drawing with a + color and Assigning a Font to a Graphic Context). This is done + by using this function: +
+XCBVoidCookie XCBChangeGC (XCBConnection *c, /* The XCB Connection */ XCBGCONTEXT gc, /* The Graphic Context */ - CARD32 value_mask, /* Components of the Graphic Context that have to be set */ - const CARD32 *value_list); /* Value as specified by value_mask */ --
- The value_mask parameter could take - these values: -
-- It is possible to set several attributes at the same - time (for example setting the attributes of a font and the - color which will be used to display a string), by OR'ing these - values in value_mask. Then - value_list has to be an array which - lists the value for the respective attributes. See Subsection - Drawing with a color to have an example. -
-- TODO: set the links of the 3 subsections, once they will - be written :) -
-- TODO: give an example which sets several attributes. -
-- After we have created a Graphic Context, we can draw on a - window using this Graphic Context, with a set of XCB - functions, collectively called "drawing primitive". Let see - how they are used. -
-- To draw a point, or several points, we use -
-+ CARD32 value_mask, /* Components of the Graphic Context that have to be set */ + const CARD32 *value_list); /* Value as specified by value_mask */ ++
+ The value_mask parameter could take + these values: +
++ It is possible to set several attributes at the same + time (for example setting the attributes of a font and the + color which will be used to display a string), by OR'ing these + values in value_mask. Then + value_list has to be an array which + lists the value for the respective attributes. See Subsection + Drawing with a color to have an example. +
++ TODO: set the links of the 3 subsections, once they will + be written :) +
++ TODO: give an example which sets several attributes. +
++ After we have created a Graphic Context, we can draw on a + window using this Graphic Context, with a set of XCB + functions, collectively called "drawing primitive". Let see + how they are used. +
++ To draw a point, or several points, we use +
+XCBVoidCookie XCBPolyPoint (XCBConnection *c, /* The connection to the X server */ BYTE coordinate_mode, /* Coordinate mode, usually set to CoordModeOrigin */ - XCBDRAWABLE drawable, /* The drawable on which we want to draw the point(s) */ - XCBGCONTEXT gc, /* The Graphic Context we use to draw the point(s) */ - CARD32 points_len, /* The number of points */ - const XCBPOINT *points); /* An array of points */ --
- The coordinate_mode parameter - specifies the coordinate mode. Available values are -
-- The XCBPOINT type is just a - structure with two fields (the coordinates of the point): -
-+ XCBDRAWABLE drawable, /* The drawable on which we want to draw the point(s) */ + XCBGCONTEXT gc, /* The Graphic Context we use to draw the point(s) */ + CARD32 points_len, /* The number of points */ + const XCBPOINT *points); /* An array of points */ ++
+ The coordinate_mode parameter + specifies the coordinate mode. Available values are +
++ The XCBPOINT type is just a + structure with two fields (the coordinates of the point): +
+typedef struct { INT16 x; INT16 y; } XCBPOINT;
- You could see an example in xpoints.c. TODO Set the link. -
-- To draw a line, or a polygonal line, we use -
-+ You could see an example in xpoints.c. TODO Set the link. + ++ To draw a line, or a polygonal line, we use +
+XCBVoidCookie XCBPolyLine (XCBConnection *c, /* The connection to the X server */ BYTE coordinate_mode, /* Coordinate mode, usually set to CoordModeOrigin */ - XCBDRAWABLE drawable, /* The drawable on which we want to draw the line(s) */ - XCBGCONTEXT gc, /* The Graphic Context we use to draw the line(s) */ - CARD32 points_len, /* The number of points in the polygonal line */ - const XCBPOINT *points); /* An array of points */ --- This function will draw the line between the first and the - second points, then the line between the second and the third - points, and so on. -
-- To draw a segment, or several segments, we use -
-+ XCBDRAWABLE drawable, /* The drawable on which we want to draw the line(s) */ + XCBGCONTEXT gc, /* The Graphic Context we use to draw the line(s) */ + CARD32 points_len, /* The number of points in the polygonal line */ + const XCBPOINT *points); /* An array of points */ +++ This function will draw the line between the first and the + second points, then the line between the second and the third + points, and so on. +
++ To draw a segment, or several segments, we use +
+XCBVoidCookie XCBPolySegment (XCBConnection *c, /* The connection to the X server */ XCBDRAWABLE drawable, /* The drawable on which we want to draw the segment(s) */ - XCBGCONTEXT gc, /* The Graphic Context we use to draw the segment(s) */ - CARD32 segments_len, /* The number of segments */ - const XCBSEGMENT *segments); /* An array of segments */ --- The XCBSEGMENT type is just a - structure with four fields (the coordinates of the two points - that define the segment): -
-+ XCBGCONTEXT gc, /* The Graphic Context we use to draw the segment(s) */ + CARD32 segments_len, /* The number of segments */ + const XCBSEGMENT *segments); /* An array of segments */ +++ The XCBSEGMENT type is just a + structure with four fields (the coordinates of the two points + that define the segment): +
+typedef struct { INT16 x1; INT16 y1; @@ -1106,22 +1107,22 @@ typedef struct { INT16 y2; } XCBSEGMENT;-- To draw a rectangle, or several rectangles, we use -
-++ To draw a rectangle, or several rectangles, we use +
+XCBVoidCookie XCBPolyRectangle (XCBConnection *c, /* The connection to the X server */ - XCBDRAWABLE drawable, /* The drawable on which we want to draw the rectangle(s) */ - XCBGCONTEXT gc, /* The Graphic Context we use to draw the rectangle(s) */ - CARD32 rectangles_len, /* The number of rectangles */ - const XCBRECTANGLE *rectangles); /* An array of rectangles */ --- The XCBRECTANGLE type is just a - structure with four fields (the coordinates of the top-left - corner of the rectangle, and its width and height): -
-+ XCBDRAWABLE drawable, /* The drawable on which we want to draw the rectangle(s) */ + XCBGCONTEXT gc, /* The Graphic Context we use to draw the rectangle(s) */ + CARD32 rectangles_len, /* The number of rectangles */ + const XCBRECTANGLE *rectangles); /* An array of rectangles */ +++ The XCBRECTANGLE type is just a + structure with four fields (the coordinates of the top-left + corner of the rectangle, and its width and height): +
+typedef struct { INT16 x; INT16 y; @@ -1129,24 +1130,24 @@ typedef struct { CARD16 height; } XCBRECTANGLE;-- TODO: there's no coordinate_mode. Is it normal ? -
-- To draw an elliptical arc, or several elliptical arcs, we use -
-++ TODO: there's no coordinate_mode. Is it normal ? +
++ To draw an elliptical arc, or several elliptical arcs, we use +
+XCBVoidCookie XCBPolyArc (XCBConnection *c, /* The connection to the X server */ XCBDRAWABLE drawable, /* The drawable on which we want to draw the arc(s) */ - XCBGCONTEXT gc, /* The Graphic Context we use to draw the arc(s) */ - CARD32 arcs_len, /* The number of arcs */ - const XCBARC *arcs); /* An array of arcs */ --- The XCBARC type is a structure with - six fields: -
-+ XCBGCONTEXT gc, /* The Graphic Context we use to draw the arc(s) */ + CARD32 arcs_len, /* The number of arcs */ + const XCBARC *arcs); /* An array of arcs */ +++ The XCBARC type is a structure with + six fields: +
+typedef struct { INT16 x; /* Top left x coordinate of the rectangle surrounding the ellipse */ INT16 y; /* Top left y coordinate of the rectangle surrounding the ellipse */ @@ -1156,79 +1157,79 @@ typedef struct { INT16 angle2; /* Angle at which the arc ends */ } XCBARC;---- Note: the angles are expressed in units of 1/64 of a degree, - so to have an angle of 90 degrees, starting at 0, - angle1 = 0 and - angle2 = 90 << 6. Positive angles - indicate counterclockwise motion, while negative angles - indicate clockwise motion. -
-- TODO: there's no coordinate_mode. Is it normal ? -
-- TODO: I think that (x,y) should be the center of the - ellipse, and (width, height) the radius. It's more logical. -
-- The corresponding function which fill inside the geometrical - object are listed below, without further explanation, as they - are used as the above functions. -
-- To Fill a polygon defined by the points given as arguments , - we use -
-++++ Note: the angles are expressed in units of 1/64 of a degree, + so to have an angle of 90 degrees, starting at 0, + angle1 = 0 and + angle2 = 90 << 6. Positive angles + indicate counterclockwise motion, while negative angles + indicate clockwise motion. +
++ TODO: there's no coordinate_mode. Is it normal ? +
++ TODO: I think that (x,y) should be the center of the + ellipse, and (width, height) the radius. It's more logical. +
++ The corresponding function which fill inside the geometrical + object are listed below, without further explanation, as they + are used as the above functions. +
++ To Fill a polygon defined by the points given as arguments , + we use +
+XCBVoidCookie XCBFillPoly (XCBConnection *c, XCBDRAWABLE drawable, - XCBGCONTEXT gc, - CARD8 shape, - CARD8 coordinate_mode, - CARD32 points_len, - const XCBPOINT *points); --- The shape parameter specifies a - shape that helps the server to improve performance. Available - values are -
-
- To fill one or several rectangles, we use -
-+ XCBGCONTEXT gc, + CARD8 shape, + CARD8 coordinate_mode, + CARD32 points_len, + const XCBPOINT *points); ++
+ The shape parameter specifies a + shape that helps the server to improve performance. Available + values are +
++ To fill one or several rectangles, we use +
+XCBVoidCookie XCBPolyFillRectangle (XCBConnection *c, XCBDRAWABLE drawable, - XCBGCONTEXT gc, - CARD32 rectangles_len, - const XCBRECTANGLE *rectangles); --
- To fill one or several arcs, we use -
-+ XCBGCONTEXT gc, + CARD32 rectangles_len, + const XCBRECTANGLE *rectangles); ++
+ To fill one or several arcs, we use +
+XCBVoidCookie XCBPolyFillArc (XCBConnection *c, XCBDRAWABLE drawable, - XCBGCONTEXT gc, - CARD32 arcs_len, - const XCBARC *arcs); -- -
- To illustrate these functions, here is an example that draws - four points, a polygonal line, two segments, two rectangles - and two arcs. Remark that we use events for the first time, as - an introduction to the next section. -
-+ XCBGCONTEXT gc, + CARD32 arcs_len, + const XCBARC *arcs); ++
+ To illustrate these functions, here is an example that draws + four points, a polygonal line, two segments, two rectangles + and two arcs. Remark that we use events for the first time, as + an introduction to the next section. +
+#include <stdlib.h> #include <stdio.h> @@ -1237,7 +1238,7 @@ XCBVoidCookie XCBPolyFillArc (XCBConnection *c, /* Get the depth of the screen. Needed in order to draw something */ int get_depth(XCBConnection *c, - XCBSCREEN *root) + XCBSCREEN *root) { XCBDRAWABLE drawable; XCBGetGeometryRep *geom; @@ -1317,15 +1318,15 @@ main (int argc, char *argv[]) values[0] = screen->white_pixel; values[1] = ExposureMask; XCBCreateWindow (c, /* Connection */ - 0, /* depth */ - win.window, /* window Id */ - screen->root, /* parent window */ - 0, 0, /* x, y */ - 150, 150, /* width, height */ - 10, /* border_width */ - InputOutput, /* class */ - screen->root_visual, /* visual */ - mask, values); /* masks */ + 0, /* depth */ + win.window, /* window Id */ + screen->root, /* parent window */ + 0, 0, /* x, y */ + 150, 150, /* width, height */ + 10, /* border_width */ + InputOutput, /* class */ + screen->root_visual, /* visual */ + mask, values); /* masks */ /* Map the window on the screen */ XCBMapWindow (c, win.window); @@ -1337,35 +1338,35 @@ main (int argc, char *argv[]) while ((e = XCBWaitEvent (c))) { switch (e->response_type) - { - case XCBExpose: - { - /* We draw the points */ - XCBPolyPoint (c, CoordModeOrigin, win, foreground, 4, points); - - /* We draw the polygonal line */ - XCBPolyLine (c, CoordModeOrigin, win, foreground, 4, polyline); - - /* We draw the segements */ - XCBPolySegment (c, win, foreground, 2, segments); - - /* We draw the rectangles */ - XCBPolyRectangle (c, win, foreground, 2, rectangles); - - /* We draw the arcs */ - XCBPolyArc (c, win, foreground, 2, arcs); - - /* We flush the request */ - XCBSync (c, 0); - - break; - } - default: - { - /* Unknown event type, ignore it */ - break; - } - } + { + case XCBExpose: + { + /* We draw the points */ + XCBPolyPoint (c, CoordModeOrigin, win, foreground, 4, points); + + /* We draw the polygonal line */ + XCBPolyLine (c, CoordModeOrigin, win, foreground, 4, polyline); + + /* We draw the segements */ + XCBPolySegment (c, win, foreground, 2, segments); + + /* We draw the rectangles */ + XCBPolyRectangle (c, win, foreground, 2, rectangles); + + /* We draw the arcs */ + XCBPolyArc (c, win, foreground, 2, arcs); + + /* We flush the request */ + XCBSync (c, 0); + + break; + } + default: + { + /* Unknown event type, ignore it */ + break; + } + } /* Free the Generic Event */ free (e); } @@ -1374,7 +1375,7 @@ main (int argc, char *argv[]) }-
In an X program, everything is driven by events. Event painting on the screen is sometimes done as a response to an event (an @@ -1386,56 +1387,56 @@ main (int argc, char *argv[]) received as a set of events.
- During the creation of a window, you should give it what kind - of events it wishes to receive. Thus, you may register for - various mouse (also called pointer) events, keyboard events, - expose events, and so on. This is done for optimizing the - server-to-client connection (i.e. why send a program (that - might even be running at the other side of the globe) an event - it is not interested in ?) -
-- In XCB, you use the "value_mask" and "value_list" data in the - XCBCreateWindow() function to - register for events. Here is how we register for - Expose event when creating a window: -
-+
+ During the creation of a window, you should give it what kind + of events it wishes to receive. Thus, you may register for + various mouse (also called pointer) events, keyboard events, + expose events, and so on. This is done for optimizing the + server-to-client connection (i.e. why send a program (that + might even be running at the other side of the globe) an event + it is not interested in ?) +
++ In XCB, you use the "value_mask" and "value_list" data in the + XCBCreateWindow() function to + register for events. Here is how we register for + Expose event when creating a window: +
+mask = XCBCWEventMask; valwin[0] = ExposureMask; win.window = XCBWINDOWNew (c); XCBCreateWindow (c, depth, win.window, root->root, - 0, 0, 150, 150, 10, - InputOutput, root->root_visual, - mask, valwin); + 0, 0, 150, 150, 10, + InputOutput, root->root_visual, + mask, valwin);
- ExposureMask is a constant defined - in the "X.h" header file. If we wanted to register to several - event types, we can logically "or" them, as follows: -
-+ ExposureMask is a constant defined + in the "X.h" header file. If we wanted to register to several + event types, we can logically "or" them, as follows: + +mask = XCBCWEventMask; valwin[0] = ExposureMask | ButtonPressMask; win.window = XCBWINDOWNew (c); XCBCreateWindow (c, depth, win.window, root->root, - 0, 0, 150, 150, 10, - InputOutput, root->root_visual, - mask, valwin); --- This registers for Expose events as - well as for mouse button presses insode the created - window. You should note that a mask may represent several - event sub-types. -
-- The values that a mask could take are given - by the XCBCW enumeration: -
-+ 0, 0, 150, 150, 10, + InputOutput, root->root_visual, + mask, valwin); +++ This registers for Expose events as + well as for mouse button presses insode the created + window. You should note that a mask may represent several + event sub-types. +
++ The values that a mask could take are given + by the XCBCW enumeration: +
+typedef enum { XCBCWBackPixmap = 1L<<0, XCBCWBackPixel = 1L<<1, @@ -1454,137 +1455,137 @@ typedef enum { XCBCWCursor = 1L<<14 } XCBCW;-++-Note: we must be careful when setting the values of the valwin parameter, as they have to follow the order the - XCBCW enumeration. Here is an + XCBCW enumeration. Here is an example: -
-+ +mask = XCBCWEventMask | XCBCWBackPixmap; valwin[0] = None; /* for XCBCWBackPixmap (whose value is 1) */ valwin[1] = ExposureMask | ButtonPressMask; /* for XCBCWEventMask, whose value (2048) */ /* is superior to the one of XCBCWBackPixmap */-- If the window has already been created, we can use the - XCBConfigureWindow() function to set - the events that the window will receive. The subsection - Configuring a window shows its - prototype. As an example, here is a piece of code that - configures the window to receive the - Expose and - ButtonPressMask events: -
-++ If the window has already been created, we can use the + XCBConfigureWindow() function to set + the events that the window will receive. The subsection + Configuring a window shows its + prototype. As an example, here is a piece of code that + configures the window to receive the + Expose and + ButtonPressMask events: +
+const static CARD32 values[] = { ExposureMask | ButtonPressMask }; /* The connection c and the window win are supposed to be defined */ XCBConfigureWindow (c, win, XCBCWEventMask, values);---- Note: A common bug programmers do is adding code to handle new - event types in their program, while forgetting to add the - masks for these events in the creation of the window. Such a - programmer then should sit down for hours debugging his - program, wondering "Why doesn't my program notice that I - released the button?", only to find that they registered for - button press events but not for button release events. -
-
- After we have registered for the event types we are interested - in, we need to enter a loop of receiving events and handling - them. There are two ways to receive events: a blocking way and - a non blocking way: -
-- There are various ways to write such a loop. We present two - ways to write such a loop, with the two functions above. The - first one uses XCBWaitEvent, which - is similar to an event Xlib loop using only XNextEvent: -
-++++ Note: A common bug programmers do is adding code to handle new + event types in their program, while forgetting to add the + masks for these events in the creation of the window. Such a + programmer then should sit down for hours debugging his + program, wondering "Why doesn't my program notice that I + released the button?", only to find that they registered for + button press events but not for button release events. +
+
+ After we have registered for the event types we are interested + in, we need to enter a loop of receiving events and handling + them. There are two ways to receive events: a blocking way and + a non blocking way: +
++ There are various ways to write such a loop. We present two + ways to write such a loop, with the two functions above. The + first one uses XCBWaitEvent, which + is similar to an event Xlib loop using only XNextEvent: +
+XCBGenericEvent *e; while ((e = XCBWaitEvent (c))) { switch (e->response_type) - { - case XCBExpose: - { - /* Handle the Expose event type */ - XCBExposeEvent *ev = (XCBExposeEvent *)e; - - /* ... */ - - break; - } - case XCBButtonPress: - { - /* Handle the ButtonPress event type */ - XCBButtonPressEvent *ev = (XCBButtonPressEvent *)e; - - /* ... */ - - break; - } - default: - { - /* Unknown event type, ignore it */ - break; - } - } + { + case XCBExpose: + { + /* Handle the Expose event type */ + XCBExposeEvent *ev = (XCBExposeEvent *)e; + + /* ... */ + + break; + } + case XCBButtonPress: + { + /* Handle the ButtonPress event type */ + XCBButtonPressEvent *ev = (XCBButtonPressEvent *)e; + + /* ... */ + + break; + } + default: + { + /* Unknown event type, ignore it */ + break; + } + } /* Free the Generic Event */ free (e); }-
- You will certainly want to use XCBPollForEvent(XCBConnection *c, int - *error) if, in Xlib, you use XPending: -
-++ You will certainly want to use XCBPollForEvent(XCBConnection *c, int + *error) if, in Xlib, you use XPending: +
+while (XPending (display)) { XEvent ev; - XNextEvent(d, &ev); + XNextEvent(d, &ev); /* Manage your event */ }- Such a loop in XCB looks like: -
-+ Such a loop in XCB looks like: + +XCBGenericEvent *ev; while ((ev = XCBPollForEvent (conn, 0))) @@ -1592,71 +1593,71 @@ XCBConfigureWindow (c, win, XCBCWEventMask, values); /* Manage your event */ }-- The events are managed in the same way as with XCBWaitEvent. - Obviously, we will need to give the user some way of - terminating the program. This is usually done by handling a - special "quit" event, as we will soon see. -
--- -- Comparison Xlib/XCB -----
-- XNextEvent ()
----
-- XCBWaitEvent ()
----
-- XPending ()
-- XNextEvent ()
----
-- XCBPollForEvent ()
-
-
- The Expose event is one of the most - basic (and most used) events an application may receive. It - will be sent to us in one of several cases: -
- You should note the implicit assumption hidden here: the - contents of our window is lost when it is being obscured - (covered) by either windows. One may wonder why the X server - does not save this contents. The answer is: to save - memory. After all, the number of windows on a display at a - given time may be very large, and storing the contents of all - of them might require a lot of memory. Actually, there is a - way to tell the X server to store the contents of a window in - special cases, as we will see later. -
-- When we get an Expose event, we - should take the event's data from the members of the following - structure: -
-++ The events are managed in the same way as with XCBWaitEvent. + Obviously, we will need to give the user some way of + terminating the program. This is usually done by handling a + special "quit" event, as we will soon see. +
++++ Comparison Xlib/XCB +++++
+- XNextEvent () +
+++
+- XCBWaitEvent () +
+++
+- XPending () +
- XNextEvent () +
+++
+- XCBPollForEvent () +
+
+
+ The Expose event is one of the most + basic (and most used) events an application may receive. It + will be sent to us in one of several cases: +
++ You should note the implicit assumption hidden here: the + contents of our window is lost when it is being obscured + (covered) by either windows. One may wonder why the X server + does not save this contents. The answer is: to save + memory. After all, the number of windows on a display at a + given time may be very large, and storing the contents of all + of them might require a lot of memory. Actually, there is a + way to tell the X server to store the contents of a window in + special cases, as we will see later. +
++ When we get an Expose event, we + should take the event's data from the members of the following + structure: +
+typedef struct { BYTE response_type; /* The type of the event, here it is XCBExpose */ CARD8 pad0; @@ -1670,33 +1671,33 @@ typedef struct { CARD16 count; } XCBExposeEvent;-
- User input traditionally comes from two sources: the mouse - and the keyboard. Various event types exist to notify us of - user input (a key being presses on the keyboard, a key being - released on the keyboard, the mouse moving over our window, - the mouse entering (or leaving) our window, and so on. -
-- The first event type we will deal with is a mouse - button-press (or button-release) event in our window. In - order to register to such an event type, we should add one - (or more) of the following masks when we create our window: -
-- The structure to be checked for in our events loop is the - same for these two events, and is the following: -
-+
+ User input traditionally comes from two sources: the mouse + and the keyboard. Various event types exist to notify us of + user input (a key being presses on the keyboard, a key being + released on the keyboard, the mouse moving over our window, + the mouse entering (or leaving) our window, and so on. +
++ The first event type we will deal with is a mouse + button-press (or button-release) event in our window. In + order to register to such an event type, we should add one + (or more) of the following masks when we create our window: +
++ The structure to be checked for in our events loop is the + same for these two events, and is the following: +
+typedef struct { BYTE response_type; /* The type of the event, here it is XCBButtonPressEvent or XCBButtonReleaseEvent */ XCBBUTTON detail; @@ -1716,73 +1717,73 @@ typedef struct { typedef XCBButtonPressEvent XCBButtonReleaseEvent;
- The time field may be used to calculate "double-click" - situations by an application (e.g. if the mouse button was - clicked two times in a duration shorter than a given amount - of time, assume this was a double click). -
+ The time field may be used to calculate "double-click" + situations by an application (e.g. if the mouse button was + clicked two times in a duration shorter than a given amount + of time, assume this was a double click). + ++ The state field is a mask of the buttons held down during + the event. It is a bitwise OR of any of the following: +
++ Their names are self explanatory, where the first 5 refer to + the mouse buttons that are being pressed, while the rest + refer to various "special keys" that are being pressed (Mod1 + is usually the 'Alt' key or the 'Meta' key). +
++ TODO: Problem: it seems that the state does not + change when clicking with various buttons. +
++ Similar to mouse button press and release events, we also + can be notified of various mouse movement events. These can + be split into two families. One is of mouse pointer + movement while no buttons are pressed, and the second is a + mouse pointer motion while one (or more) of the buttons are + pressed (this is sometimes called "a mouse drag operation", + or just "dragging"). The following event masks may be added + during the creation of our window: +
+- The state field is a mask of the buttons held down during - the event. It is a bitwise OR of any of the following: -
-- Their names are self explanatory, where the first 5 refer to - the mouse buttons that are being pressed, while the rest - refer to various "special keys" that are being pressed (Mod1 - is usually the 'Alt' key or the 'Meta' key). -
-- TODO: Problem: it seems that the state does not - change when clicking with various buttons. -
-- Similar to mouse button press and release events, we also - can be notified of various mouse movement events. These can - be split into two families. One is of mouse pointer - movement while no buttons are pressed, and the second is a - mouse pointer motion while one (or more) of the buttons are - pressed (this is sometimes called "a mouse drag operation", - or just "dragging"). The following event masks may be added - during the creation of our window: -
-- The structure to be checked for in our events loop is the - same for these events, and is the following: -
-+ The structure to be checked for in our events loop is the + same for these events, and is the following: + +typedef struct { BYTE response_type; /* The type of the event */ BYTE detail; @@ -1799,29 +1800,29 @@ typedef struct { BOOL same_screen; } XCBMotionNotifyEvent;-
- Another type of event that applications might be interested - at, is a mouse pointer entering a window the program - controls, or leaving such a window. Some programs use these - events to show the user tht the applications is now in - focus. In order to register for such an event type, we - should add one (or more) of the following masks when we - create our window: -
-- The structure to be checked for in our events loop is the - same for these two events, and is the following: -
-+
+ Another type of event that applications might be interested + at, is a mouse pointer entering a window the program + controls, or leaving such a window. Some programs use these + events to show the user tht the applications is now in + focus. In order to register for such an event type, we + should add one (or more) of the following masks when we + create our window: +
++ The structure to be checked for in our events loop is the + same for these two events, and is the following: +
+typedef struct { BYTE response_type; /* The type of the event */ BYTE detail; @@ -1841,41 +1842,41 @@ typedef struct { typedef XCBEnterNotifyEvent XCBLeaveNotifyEvent;-
- There may be many windows on a screen, but only a single - keyboard attached to them. How does the X server then know - which window should be sent a given keyboard input ? This is - done using the keyboard focus. Only a single window on the - screen may have the keyboard focus at a given time. There - is a XCB function that allow a program to set the keyboard - focus to a given window. The user can usually set the - keyboard ficus using the window manager (often by clicking - on the title bar of the desired window). Once our window - has the keyboard focus, every key press or key release will - cause an event to be sent to our program (if it regsitered - for these event types...). -
-- If a window controlled by our program currently holds the - keyboard focus, it can receive key press and key release - events. So, we should add one (or more) of the following - masks when we create our window: -
-- The structure to be checked for in our events loop is the - same for these two events, and is the following: -
-+
+ There may be many windows on a screen, but only a single + keyboard attached to them. How does the X server then know + which window should be sent a given keyboard input ? This is + done using the keyboard focus. Only a single window on the + screen may have the keyboard focus at a given time. There + is a XCB function that allow a program to set the keyboard + focus to a given window. The user can usually set the + keyboard ficus using the window manager (often by clicking + on the title bar of the desired window). Once our window + has the keyboard focus, every key press or key release will + cause an event to be sent to our program (if it regsitered + for these event types...). +
++ If a window controlled by our program currently holds the + keyboard focus, it can receive key press and key release + events. So, we should add one (or more) of the following + masks when we create our window: +
++ The structure to be checked for in our events loop is the + same for these two events, and is the following: +
+typedef struct { BYTE response_type; /* The type of the event */ XCBKEYCODE detail; @@ -1895,22 +1896,22 @@ typedef struct { typedef XCBKeyPressEvent XCBKeyReleaseEvent;
- The detail field refer to the - physical key on the keyboard. -
-+ The detail field refer to the + physical key on the keyboard. +
+TODO: Talk about getting the ASCII code from the key code. -
-- As an example for handling events, we show a program that - creates a window, enter an events loop and check for all the - events described above, and write on the terminal the relevant - characteristics of the event. With this code, it should be - easy to add drawing operations, like those which have been - described above. -
+ ++ As an example for handling events, we show a program that + creates a window, enter an events loop and check for all the + events described above, and write on the terminal the relevant + characteristics of the event. With this code, it should be + easy to add drawing operations, like those which have been + described above. +
#include <malloc.h> #include <stdio.h> @@ -1943,15 +1944,15 @@ main (int argc, char *argv[]) PointerMotionMask | EnterWindowMask | LeaveWindowMask | KeyPressMask | KeyReleaseMask; XCBCreateWindow (c, /* Connection */ - 0, /* depth */ - win.window, /* window Id */ - screen->root, /* parent window */ - 0, 0, /* x, y */ - 150, 150, /* width, height */ - 10, /* border_width */ - InputOutput, /* class */ - screen->root_visual, /* visual */ - mask, values); /* masks */ + 0, /* depth */ + win.window, /* window Id */ + screen->root, /* parent window */ + 0, 0, /* x, y */ + 150, 150, /* width, height */ + 10, /* border_width */ + InputOutput, /* class */ + screen->root_visual, /* visual */ + mask, values); /* masks */ /* Map the window on the screen */ XCBMapWindow (c, win.window); @@ -1960,117 +1961,117 @@ main (int argc, char *argv[]) while ((e = XCBWaitEvent (c))) { switch (e->response_type) - { - case XCBExpose: - { - XCBExposeEvent *ev = (XCBExposeEvent *)e; - - printf ("Window %ld exposed. Region to be redrawn at location (%d,%d), with dimension (%d,%d)\n", - ev->window.xid, ev->x, ev->y, ev->width, ev->height); - break; - } - case XCBButtonPress: - { - XCBButtonPressEvent *ev = (XCBButtonPressEvent *)e; - int button_num = 0; - - if ((ev->state | Button1Mask) == Button1Mask) - button_num = 1; - if ((ev->state | Button2Mask) == Button2Mask) - button_num = 2; - if ((ev->state | Button3Mask) == Button3Mask) - button_num = 3; - if ((ev->state | Button4Mask) == Button4Mask) - button_num = 4; - if ((ev->state | Button5Mask) == Button5Mask) - button_num = 5; - - switch (ev->detail.id) - { - case 4: - { - printf ("Wheel Button up in window %ld, at coordinates (%d,%d)\n", + { + case XCBExpose: + { + XCBExposeEvent *ev = (XCBExposeEvent *)e; + + printf ("Window %ld exposed. Region to be redrawn at location (%d,%d), with dimension (%d,%d)\n", + ev->window.xid, ev->x, ev->y, ev->width, ev->height); + break; + } + case XCBButtonPress: + { + XCBButtonPressEvent *ev = (XCBButtonPressEvent *)e; + int button_num = 0; + + if ((ev->state | Button1Mask) == Button1Mask) + button_num = 1; + if ((ev->state | Button2Mask) == Button2Mask) + button_num = 2; + if ((ev->state | Button3Mask) == Button3Mask) + button_num = 3; + if ((ev->state | Button4Mask) == Button4Mask) + button_num = 4; + if ((ev->state | Button5Mask) == Button5Mask) + button_num = 5; + + switch (ev->detail.id) + { + case 4: + { + printf ("Wheel Button up in window %ld, at coordinates (%d,%d)\n", ev->event.xid, ev->event_x, ev->event_y); - break; - } - case 5: - { - printf ("Wheel Button down in window %ld, at coordinates (%d,%d)\n", + break; + } + case 5: + { + printf ("Wheel Button down in window %ld, at coordinates (%d,%d)\n", ev->event.xid, ev->event_x, ev->event_y); - break; - } - default: - printf ("Button %d pressed in window %ld, at coordinates (%d,%d)\n", + break; + } + default: + printf ("Button %d pressed in window %ld, at coordinates (%d,%d)\n", ev->detail.id, ev->event.xid, ev->event_x, ev->event_y); - } - break; - } - case XCBButtonRelease: - { - XCBButtonReleaseEvent *ev = (XCBButtonReleaseEvent *)e; - int button_num = 0; - - if ((ev->state | Button1Mask) == Button1Mask) - button_num = 1; - if ((ev->state | Button2Mask) == Button2Mask) - button_num = 2; - if ((ev->state | Button3Mask) == Button3Mask) - button_num = 3; - if ((ev->state | Button4Mask) == Button4Mask) - button_num = 4; - if ((ev->state | Button5Mask) == Button5Mask) - button_num = 5; - - printf ("Button %d released in window %ld, at coordinates (%d,%d)\n", + } + break; + } + case XCBButtonRelease: + { + XCBButtonReleaseEvent *ev = (XCBButtonReleaseEvent *)e; + int button_num = 0; + + if ((ev->state | Button1Mask) == Button1Mask) + button_num = 1; + if ((ev->state | Button2Mask) == Button2Mask) + button_num = 2; + if ((ev->state | Button3Mask) == Button3Mask) + button_num = 3; + if ((ev->state | Button4Mask) == Button4Mask) + button_num = 4; + if ((ev->state | Button5Mask) == Button5Mask) + button_num = 5; + + printf ("Button %d released in window %ld, at coordinates (%d,%d)\n", ev->detail.id, ev->event.xid, ev->event_x, ev->event_y); - break; - } - case XCBMotionNotify: - { - XCBMotionNotifyEvent *ev = (XCBMotionNotifyEvent *)e; - - printf ("Mouse moved in window %ld, at coordinates (%d,%d)\n", + break; + } + case XCBMotionNotify: + { + XCBMotionNotifyEvent *ev = (XCBMotionNotifyEvent *)e; + + printf ("Mouse moved in window %ld, at coordinates (%d,%d)\n", ev->event.xid, ev->event_x, ev->event_y); - break; - } - case XCBEnterNotify: - { - XCBEnterNotifyEvent *ev = (XCBEnterNotifyEvent *)e; - - printf ("Mouse entered window %ld, at coordinates (%d,%d)\n", + break; + } + case XCBEnterNotify: + { + XCBEnterNotifyEvent *ev = (XCBEnterNotifyEvent *)e; + + printf ("Mouse entered window %ld, at coordinates (%d,%d)\n", ev->event.xid, ev->event_x, ev->event_y); - break; - } - case XCBLeaveNotify: - { - XCBLeaveNotifyEvent *ev = (XCBLeaveNotifyEvent *)e; - - printf ("Mouse leaved window %ld, at coordinates (%d,%d)\n", + break; + } + case XCBLeaveNotify: + { + XCBLeaveNotifyEvent *ev = (XCBLeaveNotifyEvent *)e; + + printf ("Mouse leaved window %ld, at coordinates (%d,%d)\n", ev->event.xid, ev->event_x, ev->event_y); - break; - } - case XCBKeyPress: - { - XCBKeyPressEvent *ev = (XCBKeyPressEvent *)e; + break; + } + case XCBKeyPress: + { + XCBKeyPressEvent *ev = (XCBKeyPressEvent *)e; - printf ("Key pressed in window %ld\n", + printf ("Key pressed in window %ld\n", ev->event.xid); - break; - } - case XCBKeyRelease: - { - XCBKeyReleaseEvent *ev = (XCBKeyReleaseEvent *)e; + break; + } + case XCBKeyRelease: + { + XCBKeyReleaseEvent *ev = (XCBKeyReleaseEvent *)e; - printf ("Key releaseed in window %ld\n", + printf ("Key releaseed in window %ld\n", ev->event.xid); - break; - } - default: - { - /* Unknown event type, ignore it */ - break; - } - } + break; + } + default: + { + /* Unknown event type, ignore it */ + break; + } + } /* Free the Generic Event */ free (e); } @@ -2079,7 +2080,7 @@ main (int argc, char *argv[]) }
Besides drawing graphics on a window, we often want to draw text. Text strings have two major properties: the characters to @@ -2089,22 +2090,22 @@ main (int argc, char *argv[]) draw the text in a window, using the Graphic Context.
- In order to support flexible fonts, a font structure is - defined. You know what ? Its an Id: -
-+
+ In order to support flexible fonts, a font structure is + defined. You know what ? Its an Id: +
+typedef struct { CARD32 xid; } XCBFONT;-
- It is used to contain information about a font, and is passed - to several functions that handle fonts selection and text drawing. -
++ It is used to contain information about a font, and is passed + to several functions that handle fonts selection and text drawing. +
After we have seen how to create windows and draw on them, we take one step back, and look at how our windows are interacting @@ -2119,62 +2120,62 @@ typedef struct { treat our application's windows.
- Many of the parameters communicated to the window manager are - passed using data called "properties". These properties are - attached by the X server to different windows, and are stores - in a format that makes it possible to read them from different - machines that may use different architectures (remember that - an X client program may run on a remote machine). -
-- The property and its type (a string, an integer, etc) are - Id. Their type are XCBATOM: -
-+
+ Many of the parameters communicated to the window manager are + passed using data called "properties". These properties are + attached by the X server to different windows, and are stores + in a format that makes it possible to read them from different + machines that may use different architectures (remember that + an X client program may run on a remote machine). +
++ The property and its type (a string, an integer, etc) are + Id. Their type are XCBATOM: +
+typedef struct { CARD32 xid; } XCBATOM;-
- To change the property of a window, we use the following - function: -
-++ To change the property of a window, we use the following + function: +
+XCBVoidCookie XCBChangeProperty (XCBConnection *c, /* Connection to the X server */ CARD8 mode, /* Property mode */ - XCBWINDOW window, /* Window */ - XCBATOM property, /* Property to change */ - XCBATOM type, /* Type of the property */ - CARD8 format, /* Format of the property (8, 16, 32) */ - CARD32 data_len, /* Length of the data parameter */ - const void *data); /* Data */ --- The mode parameter coud be one of - the following value (defined in the X.h header file): -
-
- The firt thing we want to do would be to set the name for our - window. This is done using the - XCBChangeProperty() function. This - name may be used by the window manager as the title of the - window (in the title bar), in a task list, etc. The property - atom to use to set the name of a window is - WM_NAME (and - WM_ICON_NAME for the iconified - window) and its type is STRING. Here - is an example of utilization: -
-+ XCBWINDOW window, /* Window */ + XCBATOM property, /* Property to change */ + XCBATOM type, /* Type of the property */ + CARD8 format, /* Format of the property (8, 16, 32) */ + CARD32 data_len, /* Length of the data parameter */ + const void *data); /* Data */ ++
+ The mode parameter coud be one of + the following value (defined in the X.h header file): +
++ The firt thing we want to do would be to set the name for our + window. This is done using the + XCBChangeProperty() function. This + name may be used by the window manager as the title of the + window (in the title bar), in a task list, etc. The property + atom to use to set the name of a window is + WM_NAME (and + WM_ICON_NAME for the iconified + window) and its type is STRING. Here + is an example of utilization: +
+#include <string.h> #include <X11/XCB/xcb.h> @@ -2202,25 +2203,25 @@ main (int argc, char *argv[]) /* Create the window */ XCBCreateWindow (c, /* Connection */ - 0, /* depth */ - win.window, /* window Id */ - screen->root, /* parent window */ - 0, 0, /* x, y */ - 250, 150, /* width, height */ - 10, /* border_width */ - InputOutput, /* class */ - screen->root_visual, /* visual */ - 0, NULL); /* masks, not used */ + 0, /* depth */ + win.window, /* window Id */ + screen->root, /* parent window */ + 0, 0, /* x, y */ + 250, 150, /* width, height */ + 10, /* border_width */ + InputOutput, /* class */ + screen->root_visual, /* visual */ + 0, NULL); /* masks, not used */ /* Set the title of the window */ XCBChangeProperty(c, PropModeReplace, win.window, - WM_NAME, STRING, 8, - strlen(title), title); + WM_NAME, STRING, 8, + strlen(title), title); /* Set the title of the window icon */ XCBChangeProperty(c, PropModeReplace, win.window, - WM_ICON_NAME, STRING, 8, - strlen(title_icon), title_icon); + WM_ICON_NAME, STRING, 8, + strlen(title_icon), title_icon); /* Map the window on the screen */ XCBMapWindow (c, win.window); @@ -2232,21 +2233,21 @@ main (int argc, char *argv[]) return 1; }-
Note: the use of the atoms needs our program to be compiled and linked against xcb_atom, so that we have to use -
-+ +
gcc prog.c -o prog `pkg-config --cflags --libs xcb_atom`-
- for the program to compile fine. -
-One more thing we can do to our window is manipulate them on the screen (resize them, move them, raise or lower them, iconify @@ -2254,87 +2255,87 @@ gcc prog.c -o prog `pkg-config --cflags --libs xcb_atom` by XCB for this purpose.
- The first pair of operations we can apply on a window is - mapping it, or un-mapping it. Mapping a window causes the - window to appear on the screen, as we have seen in our simple - window program example. Un-mapping it causes it to be removed - from the screen (although the window as a logical entity still - exists). This gives the effect of making a window hidden - (unmapped) and shown again (mapped). For example, if we have a - dialog box window in our program, instead of creating it every - time the user asks to open it, we can create the window once, - in an un-mapped mode, and when the user asks to open it, we - simply map the window on the screen. When the user clicked the - 'OK' or 'Cancel' button, we simply un-map the window. This is - much faster than creating and destroying the window, however, - the cost is wasted resources, both on the client side, and on - the X server side. -
-- To map a window, you use the following function: -
-+
+ The first pair of operations we can apply on a window is + mapping it, or un-mapping it. Mapping a window causes the + window to appear on the screen, as we have seen in our simple + window program example. Un-mapping it causes it to be removed + from the screen (although the window as a logical entity still + exists). This gives the effect of making a window hidden + (unmapped) and shown again (mapped). For example, if we have a + dialog box window in our program, instead of creating it every + time the user asks to open it, we can create the window once, + in an un-mapped mode, and when the user asks to open it, we + simply map the window on the screen. When the user clicked the + 'OK' or 'Cancel' button, we simply un-map the window. This is + much faster than creating and destroying the window, however, + the cost is wasted resources, both on the client side, and on + the X server side. +
++ To map a window, you use the following function: +
+XCBVoidCookie XCBMapWindow(XCBConnection *c, XCBWINDOW window);
- To have a simple example, see the example - above. The mapping operation will cause an - Expose event to be sent to our - application, unless the window is completely covered by other - windows. -
-- Un-mapping a window is also simple. You use the function -
-+ To have a simple example, see the example + above. The mapping operation will cause an + Expose event to be sent to our + application, unless the window is completely covered by other + windows. + ++ Un-mapping a window is also simple. You use the function +
+XCBVoidCookie XCBUnmapWindow(XCBConnection *c, XCBWINDOW window);-- The utilization of this function is the same as - XCBMapWindow(). -
-
- As we have seen when we have created our first window, in the - X Events subsection, we can set some attributes to the window - (that is, the position, the size, the events the window will - receive, etc). If we want to modify them, but the window is - already created, we can change them by using the following - function: -
-++ The utilization of this function is the same as + XCBMapWindow(). +
+
+ As we have seen when we have created our first window, in the + X Events subsection, we can set some attributes to the window + (that is, the position, the size, the events the window will + receive, etc). If we want to modify them, but the window is + already created, we can change them by using the following + function: +
+XCBVoidCookie XCBConfigureWindow (XCBConnection *c, /* The connection to the X server*/ XCBWINDOW window, /* The window to configure */ - CARD16 value_mask, /* The mask */ - const CARD32 *value_list); /* The values to set */ --
- We set the value_mask to one or - several mask values that are in the X.h header: -
- We then give to value_mask the new - value. We now describe how to use - XCBConfigureWindow in some useful - situations. -
-- An operation we might want to do with windows is to move them - to a different location. This can be done like this: -
-+ CARD16 value_mask, /* The mask */ + const CARD32 *value_list); /* The values to set */ ++
+ We set the value_mask to one or + several mask values that are in the X.h header: +
++ We then give to value_mask the new + value. We now describe how to use + XCBConfigureWindow in some useful + situations. +
++ An operation we might want to do with windows is to move them + to a different location. This can be done like this: +
+const static CARD32 values[] = { 10, 20 }; /* The connection c and the window win are supposed to be defined */ @@ -2342,18 +2343,18 @@ const static CARD32 values[] = { 10, 20 }; /* Move the window to coordinates x = 10 and y = 20 */ XCBConfigureWindow (c, win, CWX | CWY, values);-
- Note that when the window is moved, it might get partially - exposed or partially hidden by other windows, and thus we - might get Expose events due to this - operation. -
-- Yet another operation we can do is to change the size of a - window. This is done using the following code: -
-++ Note that when the window is moved, it might get partially + exposed or partially hidden by other windows, and thus we + might get Expose events due to this + operation. +
+
+ Yet another operation we can do is to change the size of a + window. This is done using the following code: +
+const static CARD32 values[] = { 200, 300 }; /* The connection c and the window win are supposed to be defined */ @@ -2361,11 +2362,11 @@ const static CARD32 values[] = { 200, 300 }; /* Resize the window to width = 10 and height = 20 */ XCBConfigureWindow (c, win, CWWidth | CWHeight, values);-
- We can also combine the move and resize operations using one - single call to XCBConfigureWindow: -
-++ We can also combine the move and resize operations using one + single call to XCBConfigureWindow: +
+const static CARD32 values[] = { 10, 20, 200, 300 }; /* The connection c and the window win are supposed to be defined */ @@ -2374,17 +2375,17 @@ const static CARD32 values[] = { 10, 20, 200, 300 }; /* and resize the window to width = 10 and height = 20 */ XCBConfigureWindow (c, win, CWX | CWY | CWWidth | CWHeight, values);-
- Until now, we changed properties of a single window. We'll see - that there are properties that relate to the window and other - windows. One of hem is the stacking order. That is, the order - in which the windows are layered on top of each other. The - front-most window is said to be on the top of the stack, while - the back-most window is at the bottom of the stack. Here is - how to manipulate our windows stack order: -
-+
+ Until now, we changed properties of a single window. We'll see + that there are properties that relate to the window and other + windows. One of hem is the stacking order. That is, the order + in which the windows are layered on top of each other. The + front-most window is said to be on the top of the stack, while + the back-most window is at the bottom of the stack. Here is + how to manipulate our windows stack order: +
+const static CARD32 values[] = { Above }; /* The connection c and the window win are supposed to be defined */ @@ -2392,7 +2393,7 @@ const static CARD32 values[] = { Above }; /* Move the window on the top of the stack */ XCBConfigureWindow (c, win, CWStackMode, values);-
+const static CARD32 values[] = { Below }; /* The connection c and the window win are supposed to be defined */ @@ -2400,16 +2401,16 @@ const static CARD32 values[] = { Below }; /* Move the window on the bottom of the stack */ XCBConfigureWindow (c, win, CWStackMode, values);-
- Just like we can set various attributes of our windows, we can - also ask the X server supply the current values of these - attributes. For example, we can check where a window is - located on the screen, what is its current size, whether it is - mapped or not, etc. The structure that contains some of this - information is -
-+
+ Just like we can set various attributes of our windows, we can + also ask the X server supply the current values of these + attributes. For example, we can check where a window is + located on the screen, what is its current size, whether it is + mapped or not, etc. The structure that contains some of this + information is +
+typedef struct { BYTE response_type; CARD8 depth; /* depth of the window */ @@ -2424,9 +2425,9 @@ typedef struct { } XCBGetGeometryRep;
- XCB fill this structure with two functions: -
-+ XCB fill this structure with two functions: + +XCBGetGeometryCookie XCBGetGeometry (XCBConnection *c, XCBDRAWABLE drawable); XCBGetGeometryRep *XCBGetGeometryReply (XCBConnection *c, @@ -2434,9 +2435,9 @@ XCBGetGeometryRep *XCBGetGeometryReply (XCBConnection *c, XCBGenericError **e);- You use them as follows: -
-+ You use them as follows: + +XCBConnection *c; XCBDRAWABLE win; XCBGetGeometryRep *geom; @@ -2450,23 +2451,23 @@ XCBGetGeometryRep *XCBGetGeometryReply (XCBConnection *c, free (geom);- Remark that you have to free the structure, as - XCBGetGeometryReply allocates a - newly one. -
-- One problem is that the returned location of the window is - relative to its parent window. This makes these coordinates - rather useless for any window manipulation functions, like - moving it on the screen. In order to overcome this problem, we - need to take a two-step operation. First, we find out the Id - of the parent window of our window. We then translate the - above relative coordinates to the screen coordinates. -
-- To get the Id of the parent window, we need this structure: -
-+ Remark that you have to free the structure, as + XCBGetGeometryReply allocates a + newly one. + ++ One problem is that the returned location of the window is + relative to its parent window. This makes these coordinates + rather useless for any window manipulation functions, like + moving it on the screen. In order to overcome this problem, we + need to take a two-step operation. First, we find out the Id + of the parent window of our window. We then translate the + above relative coordinates to the screen coordinates. +
++ To get the Id of the parent window, we need this structure: +
+typedef struct { BYTE response_type; CARD8 pad0; @@ -2479,19 +2480,19 @@ typedef struct { } XCBQueryTreeRep;- To fill this structure, we use these two functions: -
-+ To fill this structure, we use these two functions: + +XCBQueryTreeCookie XCBQueryTree (XCBConnection *c, XCBWINDOW window); XCBQueryTreeRep *XCBQueryTreeReply (XCBConnection *c, XCBQueryTreeCookie cookie, - XCBGenericError **e); + XCBGenericError **e);- The translated coordinates will be found in this structure: -
-+ The translated coordinates will be found in this structure: + +typedef struct { BYTE response_type; BOOL same_screen; @@ -2503,22 +2504,22 @@ typedef struct { } XCBTranslateCoordinatesRep;- As usual, we need two functions to fill this structure: -
-+ As usual, we need two functions to fill this structure: + +XCBTranslateCoordinatesCookie XCBTranslateCoordinates (XCBConnection *c, XCBWINDOW src_window, - XCBWINDOW dst_window, - INT16 src_x, - INT16 src_y); + XCBWINDOW dst_window, + INT16 src_x, + INT16 src_y); XCBTranslateCoordinatesRep *XCBTranslateCoordinatesReply (XCBConnection *c, - XCBTranslateCoordinatesCookie cookie, - XCBGenericError **e); + XCBTranslateCoordinatesCookie cookie, + XCBGenericError **e);- We use them as follows: -
-+ We use them as follows: + +XCBConnection *c; XCBDRAWABLE win; XCBGetGeometryRep *geom; @@ -2538,8 +2539,8 @@ XCBTranslateCoordinatesRep *XCBTranslateCoordinatesReply (XCBConnection trans = XCBTranslateCoordinatesReply (c, XCBTranslateCoordinates (c, win, - tree->parent, - geom->x, geom->y), + tree->parent, + geom->x, geom->y), 0); if (!trans) return 0; @@ -2551,21 +2552,21 @@ XCBTranslateCoordinatesRep *XCBTranslateCoordinatesReply (XCBConnection free (geom);- Of course, as for geom, - tree and - trans have to be freed. -
-- The work is a bit hard, but XCB is a very low-level library. -
-- TODO: the utilization of these functions should be a - prog, which displays the coordinates of the window. -
-- There is another structure that gives informations about our window: -
-+ Of course, as for geom, + tree and + trans have to be freed. + ++ The work is a bit hard, but XCB is a very low-level library. +
++ TODO: the utilization of these functions should be a + prog, which displays the coordinates of the window. +
++ There is another structure that gives informations about our window: +
+typedef struct { BYTE response_type; CARD8 backing_store; @@ -2588,19 +2589,19 @@ typedef struct { } XCBGetWindowAttributesRep;- XCB supplies these two functions to fill it: -
-+ XCB supplies these two functions to fill it: + +XCBGetWindowAttributesCookie XCBGetWindowAttributes (XCBConnection *c, XCBWINDOW window); XCBGetWindowAttributesRep *XCBGetWindowAttributesReply (XCBConnection *c, XCBGetWindowAttributesCookie cookie, - XCBGenericError **e); + XCBGenericError **e);- You use them as follows: -
-+ You use them as follows: + +XCBConnection *c; XCBDRAWABLE win; XCBGetWindowAttributesRep *attr; @@ -2617,93 +2618,93 @@ XCBGetWindowAttributesRep *XCBGetWindowAttributesReply (XCBConnection free (attr);- As for geom, - attr has to be freed. -
+ As for geom, + attr has to be freed. +
Up until now, all our painting operation were done using black and white. We will (finally) see now how to draw using colors.
- In the beginning, there were not enough colors. Screen - controllers could only support a limited number of colors - simultaneously (initially 2, then 4, 16 and 256). Because of - this, an application could not just ask to draw in a "light - purple-red" color, and expect that color to be available. Each - application allocated the colors it needed, and when all the - color entries (4, 16, 256 colors) were in use, the next color - allocation would fail. -
-- Thus, the notion of "a color map" was introduced. A color map - is a table whose size is the same as the number of - simultaneous colors a given screen controller. Each entry - contained the RGB (Red, Green and Blue) values of a different - color (all colors can be drawn using some combination of red, - green and blue). When an application wants to draw on the - screen, it does not specify which color to use. Rather, it - specifies which color entry of some color map to be used - during this drawing. Change the value in this color map entry - and the drawing will use a different color. -
-- In order to be able to draw using colors that got something to - do with what the programmer intended, color map allocation - functions are supplied. You could ask to allocate entry for a - color with a set of RGB values. If one already existed, you - would get its index in the table. If none existed, and the - table was not full, a new cell would be allocated to contain - the given RGB values, and its index returned. If the table was - full, the procedure would fail. You could then ask to get a - color map entry with a color that is closest to the one you - were asking for. This would mean that the actual drawing on - the screen would be done using colors similar to what you - wanted, but not the same. -
-- On today's more modern screens where one runs an X server with - support for 16 million colors, this limitation looks a little - silly, but remember that there are still older computers with - older graphics cards out there. Using color map, support for - these screen becomes transparent to you. On a display - supporting 16 million colors, any color entry allocation - request would succeed. On a display supporting a limited - number of colors, some color allocation requests would return - similar colors. It won't look as good, but your application - would still work. -
-- When you draw using XCB, you can choose to use the standard - color map of the screen your window is displayed on, or you - can allocate a new color map and apply it to a window. In the - latter case, each time the mouse moves onto your window, the - screen color map will be replaced by your window's color map, - and you'll see all the other windows on screen change their - colors into something quite bizzare. In fact, this is the - effect you get with X applications that use the "-install" - command line option. -
-- In XCB, a color map is (as often in X) an Id: -
-+
+ In the beginning, there were not enough colors. Screen + controllers could only support a limited number of colors + simultaneously (initially 2, then 4, 16 and 256). Because of + this, an application could not just ask to draw in a "light + purple-red" color, and expect that color to be available. Each + application allocated the colors it needed, and when all the + color entries (4, 16, 256 colors) were in use, the next color + allocation would fail. +
++ Thus, the notion of "a color map" was introduced. A color map + is a table whose size is the same as the number of + simultaneous colors a given screen controller. Each entry + contained the RGB (Red, Green and Blue) values of a different + color (all colors can be drawn using some combination of red, + green and blue). When an application wants to draw on the + screen, it does not specify which color to use. Rather, it + specifies which color entry of some color map to be used + during this drawing. Change the value in this color map entry + and the drawing will use a different color. +
++ In order to be able to draw using colors that got something to + do with what the programmer intended, color map allocation + functions are supplied. You could ask to allocate entry for a + color with a set of RGB values. If one already existed, you + would get its index in the table. If none existed, and the + table was not full, a new cell would be allocated to contain + the given RGB values, and its index returned. If the table was + full, the procedure would fail. You could then ask to get a + color map entry with a color that is closest to the one you + were asking for. This would mean that the actual drawing on + the screen would be done using colors similar to what you + wanted, but not the same. +
++ On today's more modern screens where one runs an X server with + support for 16 million colors, this limitation looks a little + silly, but remember that there are still older computers with + older graphics cards out there. Using color map, support for + these screen becomes transparent to you. On a display + supporting 16 million colors, any color entry allocation + request would succeed. On a display supporting a limited + number of colors, some color allocation requests would return + similar colors. It won't look as good, but your application + would still work. +
++ When you draw using XCB, you can choose to use the standard + color map of the screen your window is displayed on, or you + can allocate a new color map and apply it to a window. In the + latter case, each time the mouse moves onto your window, the + screen color map will be replaced by your window's color map, + and you'll see all the other windows on screen change their + colors into something quite bizzare. In fact, this is the + effect you get with X applications that use the "-install" + command line option. +
++ In XCB, a color map is (as often in X) an Id: +
+typedef struct { CARD32 xid; } XCBCOLORMAP;-
- In order to access the screen's default color map, you just - have to retrieve the default_colormap - field of the XCBSCREEN structure - (see Section - Checking basic information about a connection): -
-++ In order to access the screen's default color map, you just + have to retrieve the default_colormap + field of the XCBSCREEN structure + (see Section + Checking basic information about a connection): +
+#include <stdio.h> #include <X11/XCB/xcb.h> @@ -2724,33 +2725,33 @@ main (int argc, char *argv[]) return 1; }-- This will return the color map used by default on the first - screen (again, remember that an X server may support several - different screens, each of which might have its own resources). -
-- The other option, that of allocating a new colormap, works as - follows. We first ask the X server to give an Id to our color - map, with this function: -
-++ This will return the color map used by default on the first + screen (again, remember that an X server may support several + different screens, each of which might have its own resources). +
++ The other option, that of allocating a new colormap, works as + follows. We first ask the X server to give an Id to our color + map, with this function: +
+XCBCOLORMAP XCBCOLORMAPNew (XCBConnection *c);-- Then, we create the color map with -
-++ Then, we create the color map with +
+XCBVoidCookie XCBCreateColormap (XCBConnection *c, /* Pointer to the XCBConnection structure */ BYTE alloc, /* Colormap entries to be allocated (AllocNone or AllocAll) */ - XCBCOLORMAP mid, /* Id of the color map */ - XCBWINDOW window, /* Window on whose screen the colormap will be created */ - XCBVISUALID visual); /* Id of the visual supported by the screen */ --- Here is an example of creation of a new color map: -
-+ XCBCOLORMAP mid, /* Id of the color map */ + XCBWINDOW window, /* Window on whose screen the colormap will be created */ + XCBVISUALID visual); /* Id of the visual supported by the screen */ +++ Here is an example of creation of a new color map: +
+#include <X11/XCB/xcb.h> int @@ -2774,51 +2775,51 @@ main (int argc, char *argv[]) }- Note that the window parameter is only used to allow the X - server to create the color map for the given screen. We can - then use this color map for any window drawn on the same screen. -
-- To free a color map, it suffices to use this function: -
-+ Note that the window parameter is only used to allow the X + server to create the color map for the given screen. We can + then use this color map for any window drawn on the same screen. + ++ To free a color map, it suffices to use this function: +
+XCBVoidCookie XCBFreeColormap (XCBConnection *c, /* The connection */ XCBCOLORMAP cmap); /* The color map */- -- Comparison Xlib/XCB + Comparison Xlib/XCB +++++
+- XCreateColormap () +
+++
+- XCBCOLORMAPNew () +
- XCBCreateColormap () +
+++
+- XFreeColormap () +
+-+
- XCBFreeColormap () +
---
-- XCreateColormap ()
----
-- XCBCOLORMAPNew ()
-- XCBCreateColormap ()
----
-- XFreeColormap ()
---
-- XCBFreeColormap ()
-
- Once we got access to some color map, we can start allocating - colors. The informations related to a color are stored in the - following structure: -
-+
+
+ Once we got access to some color map, we can start allocating + colors. The informations related to a color are stored in the + following structure: +
+typedef struct { BYTE response_type; CARD8 pad0; @@ -2837,12 +2838,12 @@ typedef struct {XCBAllocColorCookie XCBAllocColor (XCBConnection *c, XCBCOLORMAP cmap, - CARD16 red, - CARD16 green, - CARD16 blue); + CARD16 red, + CARD16 green, + CARD16 blue); XCBAllocColorRep *XCBAllocColorReply (XCBConnection *c, XCBAllocColorCookie cookie, - XCBGenericError **e); + XCBGenericError **e);The fuction XCBAllocColor() takes the @@ -2892,7 +2893,7 @@ main (int argc, char *argv[]) TODO: Talk about freeing colors.
One thing many so-called "Multi-Media" applications need to do, is display images. In the X world, this is done using bitmaps @@ -2910,146 +2911,146 @@ main (int argc, char *argv[]) pixmaps).
- An X bitmap is a two-color image stored in a format specific - to the X window system. When stored in a file, the bitmap data - looks like a C source file. It contains variables defining the - width and the height of the bitmap, an array containing the - bit values of the bitmap (the size of the array is - weight*height), and an optional hot-spot location (that will - be explained later, when discussing mouse cursors). -
-- An X pixmap is a format used to stored images in the memory of - an X server. This format can store both black and white images - (such as x bitmaps) as well as color images. It is the only - image format supported by the X protocol, and any image to be - drawn on screen, should be first translated into this format. -
-- In actuality, an X pixmap can be thought of as a window that - does not appear on the screen. Many graphics operations that - work on windows, will also work on pixmaps. Indeed, the type - of X pixmap in XCB is an Id like a window: -
-+
+ An X bitmap is a two-color image stored in a format specific + to the X window system. When stored in a file, the bitmap data + looks like a C source file. It contains variables defining the + width and the height of the bitmap, an array containing the + bit values of the bitmap (the size of the array is + weight*height), and an optional hot-spot location (that will + be explained later, when discussing mouse cursors). +
++ An X pixmap is a format used to stored images in the memory of + an X server. This format can store both black and white images + (such as x bitmaps) as well as color images. It is the only + image format supported by the X protocol, and any image to be + drawn on screen, should be first translated into this format. +
++ In actuality, an X pixmap can be thought of as a window that + does not appear on the screen. Many graphics operations that + work on windows, will also work on pixmaps. Indeed, the type + of X pixmap in XCB is an Id like a window: +
+typedef struct { CARD32 xid; } XCBPIXMAP;-
- In order to make the difference between a window and a pixmap, - XCB introduces a drawable type, which is a union -
-++ In order to make the difference between a window and a pixmap, + XCB introduces a drawable type, which is a union +
+typedef union { XCBWINDOW window; XCBPIXMAP pixmap; } XCBDRAWABLE;- in order to avoid confusion between a window and a pixmap. The - operations that will work indifferently on a window or a pixmap - will require a XCBDRAWABLE -
---- Remark: In Xlib, there is no specific difference between a - Drawable, a - Pixmap or a - Window: all are 32 bit long - integer. -
-
- Sometimes we want to create an un-initialized pixmap, so we - can later draw into it. This is useful for image drawing - programs (creating a new empty canvas will cause the creation - of a new pixmap on which the drawing can be stored). It is - also useful when reading various image formats: we load the - image data into memory, create a pixmap on the server, and - then draw the decoded image data onto that pixmap. -
-- To create a new pixmap, we first ask the X server to give an - Id to our pixmap, with this function: -
-+ in order to avoid confusion between a window and a pixmap. The + operations that will work indifferently on a window or a pixmap + will require a XCBDRAWABLE + ++++ Remark: In Xlib, there is no specific difference between a + Drawable, a + Pixmap or a + Window: all are 32 bit long + integer. +
+
+ Sometimes we want to create an un-initialized pixmap, so we + can later draw into it. This is useful for image drawing + programs (creating a new empty canvas will cause the creation + of a new pixmap on which the drawing can be stored). It is + also useful when reading various image formats: we load the + image data into memory, create a pixmap on the server, and + then draw the decoded image data onto that pixmap. +
++ To create a new pixmap, we first ask the X server to give an + Id to our pixmap, with this function: +
+XCBPIXMAP XCBPIXMAPNew (XCBConnection *c);
- Then, XCB supplies the following function to create new pixmaps: -
-+ Then, XCB supplies the following function to create new pixmaps: + +XCBVoidCookie XCBCreatePixmap (XCBConnection *c, /* Pointer to the XCBConnection structure */ CARD8 depth, /* Depth of the screen */ - XCBPIXMAP pid, /* Id of the pixmap */ - XCBDRAWABLE drawable, - CARD16 width, /* Width of the window (in pixels) */ - CARD16 height); /* Height of the window (in pixels) */ --- TODO: Explain the drawable parameter, and give an - example (like xpoints.c) -
-
- Once we got a handle to a pixmap, we can draw it on some - window, using the following function: -
-+ XCBPIXMAP pid, /* Id of the pixmap */ + XCBDRAWABLE drawable, + CARD16 width, /* Width of the window (in pixels) */ + CARD16 height); /* Height of the window (in pixels) */ ++
+ TODO: Explain the drawable parameter, and give an + example (like xpoints.c) +
++ Once we got a handle to a pixmap, we can draw it on some + window, using the following function: +
+XCBVoidCookie XCBCopyArea (XCBConnection *c, /* Pointer to the XCBConnection structure */ XCBDRAWABLE src_drawable, /* The Drawable we want to paste */ - XCBDRAWABLE dst_drawable, /* The Drawable on which we copy the previous Drawable */ - XCBGCONTEXT gc, /* A Graphic Context */ - INT16 src_x, /* Top left x coordinate of the region we want to copy */ - INT16 src_y, /* Top left y coordinate of the region we want to copy */ - INT16 dst_x, /* Top left x coordinate of the region where we want to copy */ - INT16 dst_y, /* Top left y coordinate of the region where we want to copy */ - CARD16 width, /* Width of the region we want to copy */ - CARD16 height); /* Height of the region we want to copy */ --
- As you can see, we could copy the whole pixmap, as well as - only a given rectangle of the pixmap. This is useful to - optimize the drawing speed: we could copy only what we have - modified in the pixmap. -
-- One important note should be made: it is possible to - create pixmaps with different depths on the same screen. When - we perform copy operations (a pixmap onto a window, etc), we - should make sure that both source and target have the same - depth. If they have a different depth, the operation would - fail. The exception to this is if we copy a specific bit plane - of the source pixmap using the - XCBCopyPlane function. In such an - event, we can copy a specific plain to the target window (in - actuality, setting a specific bit in the color of each pixel - copied). This can be used to generate strange graphic effects - in widow, but that is beyond the scope of this tutorial. -
-- Finally, when we are done using a given pixmap, we should free - it, in order to free resources of the X server. This is done - using this function: -
-+ XCBDRAWABLE dst_drawable, /* The Drawable on which we copy the previous Drawable */ + XCBGCONTEXT gc, /* A Graphic Context */ + INT16 src_x, /* Top left x coordinate of the region we want to copy */ + INT16 src_y, /* Top left y coordinate of the region we want to copy */ + INT16 dst_x, /* Top left x coordinate of the region where we want to copy */ + INT16 dst_y, /* Top left y coordinate of the region where we want to copy */ + CARD16 width, /* Width of the region we want to copy */ + CARD16 height); /* Height of the region we want to copy */ ++
+ As you can see, we could copy the whole pixmap, as well as + only a given rectangle of the pixmap. This is useful to + optimize the drawing speed: we could copy only what we have + modified in the pixmap. +
++ One important note should be made: it is possible to + create pixmaps with different depths on the same screen. When + we perform copy operations (a pixmap onto a window, etc), we + should make sure that both source and target have the same + depth. If they have a different depth, the operation would + fail. The exception to this is if we copy a specific bit plane + of the source pixmap using the + XCBCopyPlane function. In such an + event, we can copy a specific plain to the target window (in + actuality, setting a specific bit in the color of each pixel + copied). This can be used to generate strange graphic effects + in widow, but that is beyond the scope of this tutorial. +
++ Finally, when we are done using a given pixmap, we should free + it, in order to free resources of the X server. This is done + using this function: +
+XCBVoidCookie XCBFreePixmap (XCBConnection *c, /* Pointer to the XCBConnection structure */ XCBPIXMAP pixmap); /* A given pixmap */-
- Of course, after having freed it, we must not try accessing - the pixmap again. -
-- TODO: Give an example, or a link to xpoints.c -
++ Of course, after having freed it, we must not try accessing + the pixmap again. +
++ TODO: Give an example, or a link to xpoints.c +
The problem when you want to port an Xlib program to XCB is that you don't know if the Xlib function that you want to "translate" @@ -3058,7 +3059,7 @@ XCBVoidCookie XCBFreePixmap (XCBConnection *c, /* Pointer to the XCBConne provides. It's usually just a member of a structure.
This number is the file descriptor that connects the client to the server. You just have to use that function: @@ -3075,7 +3076,7 @@ XCBVoidCookie XCBFreePixmap (XCBConnection *c, /* Pointer to the XCBConne
int XCBGetFileDescriptor(XCBConnection *c);-
That number is not stored by XCB. It is returned in the second parameter of the function XCBConnect. @@ -3093,15 +3094,15 @@ int screen_default_nbr; /* you pass the name of the display you want to XCBConnect */ -c = XCBConnect (display_name, &screen_default_nbr); +c = XCBConnect (display_name, &screen_default_nbr); /* screen_default_nbr contains now the number of the default screen */ -
Not documented yet.
-You get the count of screens with the functions XCBGetSetup @@ -3134,7 +3135,7 @@ screen_count = XCBConnSetupSuccessRepRootsLength (XCBGetSetup (c)); /* screen_count contains now the count of screens */ -
You get the name of the vendor of the server hardware with the functions XCBGetSetup @@ -3158,7 +3159,7 @@ vendor[length] = '\0'; /* vendor contains now the name of the vendor. Must be freed when not used anymore */ -
You get the major version of the protocol in the XCBConnSetupSuccessRep @@ -3174,7 +3175,7 @@ protocol_major_version = XCBGetSetup (c)->protocol_major_version; /* protocol_major_version contains now the major version of the protocol */ -
You get the minor version of the protocol in the XCBConnSetupSuccessRep @@ -3190,7 +3191,7 @@ protocol_minor_version = XCBGetSetup (c)->protocol_minor_version; /* protocol_minor_version contains now the minor version of the protocol */ -
You get the number of the release of the server hardware in the XCBConnSetupSuccessRep @@ -3206,12 +3207,12 @@ release_number = XCBGetSetup (c)->release_number; /* release_number contains now the number of the release of the server hardware */ -
The name of the display is not stored in XCB. You have to store it by yourself.
-You get the bitmap scanline unit in the XCBConnSetupSuccessRep @@ -3227,7 +3228,7 @@ bitmap_format_scanline_unit = XCBGetSetup (c)->bitmap_format_scanline_unit; /* bitmap_format_scanline_unit contains now the bitmap scanline unit */ -
You get the bitmap bit order in the XCBConnSetupSuccessRep @@ -3243,7 +3244,7 @@ bitmap_format_bit_order = XCBGetSetup (c)->bitmap_format_bit_order; /* bitmap_format_bit_order contains now the bitmap bit order */ -
You get the bitmap scanline pad in the XCBConnSetupSuccessRep @@ -3259,7 +3260,7 @@ bitmap_format_scanline_pad = XCBGetSetup (c)->bitmap_format_scanline_pad; /* bitmap_format_scanline_pad contains now the bitmap scanline pad */ -
You get the image byte order in the XCBConnSetupSuccessRep @@ -3276,7 +3277,7 @@ image_byte_order = XCBGetSetup (c)->image_byte_order; /* image_byte_order contains now the image byte order */
in Xlib, ScreenOfDisplay returns a Screen structure that contains @@ -3301,7 +3302,7 @@ image_byte_order = XCBGetSetup (c)->image_byte_order; more) as, with XCB, you will use the same code.
This function returns the Xlib Screen structure. With XCB, you iterate over all the screens and @@ -3314,7 +3315,7 @@ XCBSCREEN *ScreenOfDisplay (XCBConnection *c, XCBSCREENIter iter; iter = XCBConnSetupSuccessRepRootsIter (XCBGetSetup (c)); - for (; iter.rem; --screen, XCBSCREENNext (&iter)) + for (; iter.rem; --screen, XCBSCREENNext (&iter)) if (screen == 0) return iter.data; @@ -3330,7 +3331,7 @@ XCBSCREEN *ScreenOfDisplay (XCBConnection *c, function, as they just grab a specific member of the XCBSCREEN structure.
-It is the default screen that you obtain when you connect to the X server. It suffices to call the ScreenOfDisplay @@ -3344,12 +3345,12 @@ XCBSCREEN *default_screen; /* the returned default screen */ /* you pass the name of the display you want to XCBConnect */ -c = XCBConnect (display_name, &screen_default_nbr); +c = XCBConnect (display_name, &screen_default_nbr); default_screen = ScreenOfDisplay (c, screen_default_nbr); /* default_screen contains now the default root window, or a NULL window if no screen is found */ -
@@ -3366,7 +3367,7 @@ if (screen) /* root_window contains now the root window, or a NULL window if no screen is found */-
It is the root window of the default screen. So, you call ScreenOfDisplay with the @@ -3381,14 +3382,14 @@ XCBWINDOW root_window = { 0 }; /* the returned root window */ /* you pass the name of the display you want to XCBConnect */ -c = XCBConnect (display_name, &screen_default_nbr); +c = XCBConnect (display_name, &screen_default_nbr); screen = ScreenOfDisplay (c, screen_default_nbr); if (screen) root_window = screen->root; /* root_window contains now the default root window, or a NULL window if no screen is found */ -
While a Visual is, in Xlib, a structure, in XCB, there are two types: XCBVISUALID, which is @@ -3437,12 +3438,12 @@ if (screen) XCBDEPTHIter depth_iter; depth_iter = XCBSCREENAllowedDepthsIter (screen); - for (; depth_iter.rem; XCBDEPTHNext (&depth_iter)) + for (; depth_iter.rem; XCBDEPTHNext (&depth_iter)) { XCBVISUALTYPEIter visual_iter; visual_iter = XCBDEPTHVisualsIter (depth_iter.data); - for (; visual_iter.rem; XCBVISUALTYPENext (&visual_iter)) + for (; visual_iter.rem; XCBVISUALTYPENext (&visual_iter)) { if (screen->root_visual.id == visual_iter.data->visual_id.id) { @@ -3455,7 +3456,7 @@ if (screen) /* visual_type contains now the visual structure, or a NULL visual structure if no screen is found */ -
This default Graphic Context is just a newly created Graphic Context, associated to the root window of a @@ -3487,7 +3488,7 @@ if (screen) /* gc contains now the default graphic context */ -
It is the Id of the black pixel, which is in the structure of an XCBSCREEN. @@ -3506,7 +3507,7 @@ if (screen) /* black_pixel contains now the value of the black pixel, or 0 if no screen is found */ -
It is the Id of the white pixel, which is in the structure of an XCBSCREEN. @@ -3525,7 +3526,7 @@ if (screen) /* white_pixel contains now the value of the white pixel, or 0 if no screen is found */ -
It is the width in pixels of the screen that you want, and which is in the structure of the corresponding @@ -3545,7 +3546,7 @@ if (screen) /* width_in_pixels contains now the width in pixels, or 0 if no screen is found */ -
It is the height in pixels of the screen that you want, and which is in the structure of the corresponding @@ -3565,7 +3566,7 @@ if (screen) /* height_in_pixels contains now the height in pixels, or 0 if no screen is found */ -
It is the width in millimeters of the screen that you want, and which is in the structure of the corresponding @@ -3585,7 +3586,7 @@ if (screen) /* width_in_millimeters contains now the width in millimeters, or 0 if no screen is found */ -
It is the height in millimeters of the screen that you want, and which is in the structure of the corresponding @@ -3605,7 +3606,7 @@ if (screen) /* height_in_millimeters contains now the height in millimeters, or 0 if no screen is found */ -
It is the depth (in bits) of the root window of the screen. You get it from the XCBSCREEN structure. @@ -3624,7 +3625,7 @@ if (screen) /* root_depth contains now the depth of the root window, or 0 if no screen is found */ -
This is the default colormap of the screen (and not the (default) colormap of the default screen !). As usual, you @@ -3644,7 +3645,7 @@ if (screen) /* default_colormap contains now the default colormap, or a NULL colormap if no screen is found */ -
You get the minimum installed colormaps in the XCBSCREEN structure:
@@ -3662,7 +3663,7 @@ if (screen) /* min_installed_maps contains now the minimum installed colormaps, or 0 if no screen is found */ -You get the maximum installed colormaps in the XCBSCREEN structure:
@@ -3680,7 +3681,7 @@ if (screen) /* max_installed_maps contains now the maximum installed colormaps, or 0 if no screen is found */ -You know if save_unders is set, by looking in the XCBSCREEN structure: @@ -3699,7 +3700,7 @@ if (screen) /* save_unders contains now the value of save_unders, or FALSE if no screen is found */ -
You know the value of backing_stores, by looking in the XCBSCREEN structure: @@ -3718,7 +3719,7 @@ if (screen) /* backing_stores contains now the value of backing_stores, or FALSE if no screen is found */ -
To get the current input masks, you look in the XCBSCREEN structure: @@ -3738,9 +3739,9 @@ if (screen) /* current_input_masks contains now the value of the current input masks, or FALSE if no screen is found */
in Xlib, the Screen structure stores its associated Display @@ -3748,7 +3749,7 @@ if (screen) hence, it's also not the case in XCB. So you have to store it by yourself.
-To get the colormap entries, you look in the XCBVISUALTYPE -- cgit v1.2.3