X-Git-Url: http://git.demorecorder.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=doc%2Ftutorial%2Findex.html;h=adec0acd3ad2c8ce9c5a8741a4268c06a048f13d;hb=2415c11dec5e5adb0c17f98aa52fbb371a4f8f23;hp=e39ee2ee8e01908a9f5849c94ef22e7f9ae9a48b;hpb=818811a7ac660e46d0dca1cbf9e53ad0475af330;p=free-sw%2Fxcb%2Flibxcb diff --git a/doc/tutorial/index.html b/doc/tutorial/index.html index e39ee2e..adec0ac 100644 --- a/doc/tutorial/index.html +++ b/doc/tutorial/index.html @@ -59,9 +59,10 @@
-xcb_connection_t *xcb_connect (const char *displayname, -int *screenp); +xcb_connection_t *xcb_connect (const char *displayname, + int *screenp);
The second parameter returns the screen number used for the @@ -596,24 +598,24 @@ gcc -Wall prog.c -o prog `pkg-config --cflags --libs xcb` and is opaque. Here is how the connection can be opened:
-#include <xcb/xcb.h> +#include <xcb/xcb.h> -int -main () +int +main () { -xcb_connection_t *c; + xcb_connection_t *c; /* Open the connection to the X server. Use the DISPLAY environment variable as the default display name */ c = xcb_connect (NULL, NULL); -return 0; + return 0; }
To close a connection, it suffices to use:
-void xcb_disconnect (xcb_connection_t *c); +void xcb_disconnect (xcb_connection_t *c);
-
+Once we have opened a connection to an X server, we should check some @@ -706,7 +707,7 @@ main () } printf ("\n"); - printf ("Informations of screen %ld:\n", screen->root.xid); + printf ("Informations of screen %ld:\n", screen->root); printf (" width.........: %d\n", screen->width_in_pixels); printf (" height........: %d\n", screen->height_in_pixels); printf (" white pixel...: %ld\n", screen->white_pixel); @@ -723,9 +724,7 @@ main () characterized by an Id. So, in XCB, a window is of type:
-typedef struct { - uint32_t xid; -} xcb_window_t; +typedef uint32_t xcb_window_t;
We first ask for a new Id for our window, with this function: @@ -776,7 +775,7 @@ main () { xcb_connection_t *c; xcb_screen_t *screen; - xcb_drawable_t win; + xcb_window_t win; /* Open the connection to the X server */ c = xcb_connect (NULL, NULL); @@ -785,12 +784,12 @@ main () screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data; /* Ask for our window's Id */ - win.window = xcb_generate_id(c); + win = xcb_generate_id(c); /* Create the window */ xcb_create_window (c, /* Connection */ XCB_COPY_FROM_PARENT, /* depth (same as root)*/ - win.window, /* window Id */ + win, /* window Id */ screen->root, /* parent window */ 0, 0, /* x, y */ 150, 150, /* width, height */ @@ -800,7 +799,7 @@ main () 0, NULL); /* masks, not used yet */ /* Map the window on the screen */ - xcb_map_window (c, win.window); + xcb_map_window (c, win); /* Make sure commands are sent before we pause, so window is shown */ xcb_flush (c); @@ -887,9 +886,7 @@ int xcb_aux_sync (xcb_connection_t *c); a Graphics Context is, as a window, characterized by an Id:
-typedef struct { - uint32_t xid; -} xcb_gcontext_t; +typedef uint32_t xcb_gcontext_t;
We first ask the X server to attribute an Id to our graphic @@ -931,7 +928,7 @@ main () screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data; /* Create a black graphic context for drawing in the foreground */ - win.window = screen->root; + win = screen->root; black = xcb_generate_id (c); mask = XCB_GC_FOREGROUND; value[0] = screen->black_pixel; @@ -982,8 +979,9 @@ main () 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: + color and + Assigning a Font to a Graphic Context). + This is done by using this function:
xcb_void_cookie_t xcb_change_gc (xcb_connection_t *c, /* The XCB Connection */ @@ -1291,7 +1289,7 @@ main () screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data; /* Create black (foreground) graphic context */ - win.window = screen->root; + win = screen->root; foreground = xcb_generate_id (c); mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES; @@ -1300,7 +1298,7 @@ main () xcb_create_gc (c, foreground, win, mask, values); /* Ask for our window's Id */ - win.window = xcb_generate_id(c); + win = xcb_generate_id(c); /* Create the window */ mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; @@ -1308,7 +1306,7 @@ main () values[1] = XCB_EVENT_MASK_EXPOSURE; xcb_create_window (c, /* Connection */ XCB_COPY_FROM_PARENT, /* depth */ - win.window, /* window Id */ + win, /* window Id */ screen->root, /* parent window */ 0, 0, /* x, y */ 150, 150, /* width, height */ @@ -1318,7 +1316,7 @@ main () mask, values); /* masks */ /* Map the window on the screen */ - xcb_map_window (c, win.window); + xcb_map_window (c, win); /* We flush the request */ @@ -1391,8 +1389,8 @@ main ()mask = XCB_CW_EVENT_MASK; valwin[0] = XCB_EVENT_MASK_EXPOSURE; - win.window = xcb_generate_id (c); - xcb_create_window (c, depth, win.window, root->root, + win = xcb_generate_id (c); + xcb_create_window (c, depth, win, root->root, 0, 0, 150, 150, 10, XCB_WINDOW_CLASS_INPUT_OUTPUT, root->root_visual, mask, valwin); @@ -1405,8 +1403,8 @@ main ()mask = XCB_CW_EVENT_MASK; valwin[0] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS; - win.window = xcb_generate_id (c); - xcb_create_window (c, depth, win.window, root->root, + win = xcb_generate_id (c); + xcb_create_window (c, depth, win, root->root, 0, 0, 150, 150, 10, XCB_WINDOW_CLASS_INPUT_OUTPUT, root->root_visual, mask, valwin); @@ -1455,7 +1453,7 @@ typedef enum {If the window has already been created, we can use the - xcb_configure_window() function to set + xcb_change_window_attributes() 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 @@ -1468,7 +1466,7 @@ const static uint32_t values[] = { XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTT /* The connection c and the window win are supposed to be defined */ -xcb_configure_window (c, win, XCB_CW_EVENT_MASK, values); +xcb_change_window_attributes (c, win, XCB_CW_EVENT_MASK, values);
@@ -1916,7 +1914,7 @@ main () { xcb_connection_t *c; xcb_screen_t *screen; - xcb_drawable_t win; + xcb_window_t win; xcb_generic_event_t *e; uint32_t mask = 0; uint32_t values[2]; @@ -1928,7 +1926,7 @@ main () screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data; /* Ask for our window's Id */ - win.window = xcb_generate_id (c); + win = xcb_generate_id (c); /* Create the window */ mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; @@ -1939,7 +1937,7 @@ main () XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE; xcb_create_window (c, /* Connection */ 0, /* depth */ - win.window, /* window Id */ + win, /* window Id */ screen->root, /* parent window */ 0, 0, /* x, y */ 150, 150, /* width, height */ @@ -1949,7 +1947,7 @@ main () mask, values); /* masks */ /* Map the window on the screen */ - xcb_map_window (c, win.window); + xcb_map_window (c, win); xcb_flush (c); @@ -1959,25 +1957,25 @@ main () xcb_expose_event_t *ev = (xcb_expose_event_t *)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); + ev->window, ev->x, ev->y, ev->width, ev->height); break; } case XCB_BUTTON_PRESS: { xcb_button_press_event_t *ev = (xcb_button_press_event_t *)e; print_modifiers(ev->state); - switch (ev->detail.id) { + switch (ev->detail) { case 4: printf ("Wheel Button up in window %ld, at coordinates (%d,%d)\n", - ev->event.xid, ev->event_x, ev->event_y); + ev->event, ev->event_x, ev->event_y); break; case 5: printf ("Wheel Button down in window %ld, at coordinates (%d,%d)\n", - ev->event.xid, ev->event_x, ev->event_y); + ev->event, ev->event_x, ev->event_y); 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); + ev->detail, ev->event, ev->event_x, ev->event_y); } break; } @@ -1986,28 +1984,28 @@ main () print_modifiers(ev->state); printf ("Button %d released in window %ld, at coordinates (%d,%d)\n", - ev->detail.id, ev->event.xid, ev->event_x, ev->event_y); + ev->detail, ev->event, ev->event_x, ev->event_y); break; } case XCB_MOTION_NOTIFY: { xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)e; printf ("Mouse moved in window %ld, at coordinates (%d,%d)\n", - ev->event.xid, ev->event_x, ev->event_y); + ev->event, ev->event_x, ev->event_y); break; } case XCB_ENTER_NOTIFY: { xcb_enter_notify_event_t *ev = (xcb_enter_notify_event_t *)e; printf ("Mouse entered window %ld, at coordinates (%d,%d)\n", - ev->event.xid, ev->event_x, ev->event_y); + ev->event, ev->event_x, ev->event_y); break; } case XCB_LEAVE_NOTIFY: { xcb_leave_notify_event_t *ev = (xcb_leave_notify_event_t *)e; printf ("Mouse left window %ld, at coordinates (%d,%d)\n", - ev->event.xid, ev->event_x, ev->event_y); + ev->event, ev->event_x, ev->event_y); break; } case XCB_KEY_PRESS: { @@ -2015,7 +2013,7 @@ main () print_modifiers(ev->state); printf ("Key pressed in window %ld\n", - ev->event.xid); + ev->event); break; } case XCB_KEY_RELEASE: { @@ -2023,7 +2021,7 @@ main () print_modifiers(ev->state); printf ("Key released in window %ld\n", - ev->event.xid); + ev->event); break; } default: @@ -2051,22 +2049,314 @@ main ()
- The Font structure
- In order to support flexible fonts, a font structure is + In order to support flexible fonts, a font type is defined. You know what ? It's an Id:
-typedef struct { - uint32_t xid; -} xcb_font_t; +typedef uint32_t xcb_font_t;It is used to contain information about a font, and is passed to several functions that handle fonts selection and text drawing. + We ask the X server to attribute an Id to our font with the + function:
++xcb_font_t xcb_generate_id (xcb_connection_t *c); ++
+- Opening a Font +
+ To open a font, we use the following function: +
++xcb_void_cookie_t xcb_open_font (xcb_connection_t *c, + xcb_font_t fid, + uint16_t name_len, + const char *name); +- TODO: example for picking a font and displaying some text. - Even better, also demonstrate translating keypresses to text. + The fid parameter is the font Id + defined by xcb_generate_id() (see + above). The name parameter is the + name of the font you want to open. Use the command + xlsfonts in a terminal to know which + are the fonts available on your computer. The parameter + name_len is the length of the name + of the font (given by strlen()).
+- Assigning a Font to a Graphic Context +
+ Once a font is opened, you have to create a Graphic Context + that will contain the informations about the color of the + foreground and the background used when you draw a text in a + Drawable. Here is an exemple of a Graphic Context that will + allow us to draw an opened font with a black foreground and a + white background: +
++ /* + * c is the connection + * screen is the screen where the window is displayed + * window is the window in which we will draw the text + * font is the opened font + */ + + uint32_t value_list[3]; + xcb_gcontext_t gc; + uint32_t mask; + + gc = xcb_generate_id (c); + mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT; + value_list[0] = screen->black_pixel; + value_list[1] = screen->white_pixel; + value_list[2] = font; + xcb_create_gc (c, gc, window, mask, value_list); + + /* The font is not needed anymore, so we close it */ + xcb_close_font (c, font); ++- Drawing text in a drawable +
+ To draw a text in a drawable, we use the following function: +
++xcb_void_cookie_t xcb_image_text_8 (xcb_connection_t *c, + uint8_t string_len, + xcb_drawable_t drawable, + xcb_gcontext_t gc, + int16_t x, + int16_t y, + const char *string); +++ The string parameter is the text to + draw. The location of the drawing is given by the parameters + x and y. + The base line of the text is exactly the parameter + y. +
+- Complete example +
+ This example draw a text at 10 pixels (for the base line) of + the bottom of a window. Pressing the Esc key exits the program. +
++#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <xcb/xcb.h> + +#define WIDTH 300 +#define HEIGHT 100 + + + +static xcb_gc_t gc_font_get (xcb_connection_t *c, + xcb_screen_t *screen, + xcb_window_t window, + const char *font_name); + +static void text_draw (xcb_connection_t *c, + xcb_screen_t *screen, + xcb_window_t window, + int16_t x1, + int16_t y1, + const char *label); + +static void +text_draw (xcb_connection_t *c, + xcb_screen_t *screen, + xcb_window_t window, + int16_t x1, + int16_t y1, + const char *label) +{ + xcb_void_cookie_t cookie_gc; + xcb_void_cookie_t cookie_text; + xcb_generic_error_t *error; + xcb_gcontext_t gc; + uint8_t length; + + length = strlen (label); + + gc = gc_font_get(c, screen, window, "7x13"); + + cookie_text = xcb_image_text_8_checked (c, length, window, gc, + x1, + y1, label); + error = xcb_request_check (c, cookie_text); + if (error) { + fprintf (stderr, "ERROR: can't paste text : %d\n", error->error_code); + xcb_disconnect (c); + exit (-1); + } + + cookie_gc = xcb_free_gc (c, gc); + error = xcb_request_check (c, cookie_gc); + if (error) { + fprintf (stderr, "ERROR: can't free gc : %d\n", error->error_code); + xcb_disconnect (c); + exit (-1); + } +} + +static xcb_gc_t +gc_font_get (xcb_connection_t *c, + xcb_screen_t *screen, + xcb_window_t window, + const char *font_name) +{ + uint32_t value_list[3]; + xcb_void_cookie_t cookie_font; + xcb_void_cookie_t cookie_gc; + xcb_generic_error_t *error; + xcb_font_t font; + xcb_gcontext_t gc; + uint32_t mask; + + font = xcb_generate_id (c); + cookie_font = xcb_open_font_checked (c, font, + strlen (font_name), + font_name); + + error = xcb_request_check (c, cookie_font); + if (error) { + fprintf (stderr, "ERROR: can't open font : %d\n", error->error_code); + xcb_disconnect (c); + return -1; + } + + gc = xcb_generate_id (c); + mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT; + value_list[0] = screen->black_pixel; + value_list[1] = screen->white_pixel; + value_list[2] = font; + cookie_gc = xcb_create_gc_checked (c, gc, window, mask, value_list); + error = xcb_request_check (c, cookie_gc); + if (error) { + fprintf (stderr, "ERROR: can't create gc : %d\n", error->error_code); + xcb_disconnect (c); + exit (-1); + } + + cookie_font = xcb_close_font_checked (c, font); + error = xcb_request_check (c, cookie_font); + if (error) { + fprintf (stderr, "ERROR: can't close font : %d\n", error->error_code); + xcb_disconnect (c); + exit (-1); + } + + return gc; +} + +int main () +{ + xcb_screen_iterator_t screen_iter; + xcb_connection_t *c; + const xcb_setup_t *setup; + xcb_screen_t *screen; + xcb_generic_event_t *e; + xcb_generic_error_t *error; + xcb_void_cookie_t cookie_window; + xcb_void_cookie_t cookie_map; + xcb_window_t window; + uint32_t mask; + uint32_t values[2]; + int screen_number; + + /* getting the connection */ + c = xcb_connect (NULL, &screen_number); + if (!c) { + fprintf (stderr, "ERROR: can't connect to an X server\n"); + return -1; + } + + /* getting the current screen */ + setup = xcb_get_setup (c); + + screen = NULL; + screen_iter = xcb_setup_roots_iterator (setup); + for (; screen_iter.rem != 0; --screen_number, xcb_screen_next (&screen_iter)) + if (screen_number == 0) + { + screen = screen_iter.data; + break; + } + if (!screen) { + fprintf (stderr, "ERROR: can't get the current screen\n"); + xcb_disconnect (c); + return -1; + } + + /* creating the window */ + window = xcb_generate_id (c); + mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; + values[0] = screen->white_pixel; + values[1] = + XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_POINTER_MOTION; + cookie_window = xcb_create_window_checked (c, + screen->root_depth, + window, screen->root, + 20, 200, WIDTH, HEIGHT, + 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, + screen->root_visual, + mask, values); + cookie_map = xcb_map_window_checked (c, window); + + /* error managing */ + error = xcb_request_check (c, cookie_window); + if (error) { + fprintf (stderr, "ERROR: can't create window : %d\n", error->error_code); + xcb_disconnect (c); + return -1; + } + error = xcb_request_check (c, cookie_map); + if (error) { + fprintf (stderr, "ERROR: can't map window : %d\n", error->error_code); + xcb_disconnect (c); + return -1; + } + + xcb_flush(c); + + while (1) { + e = xcb_poll_for_event(c); + if (e) { + switch (e->response_type & ~0x80) { + case XCB_EXPOSE: { + char *text; + + text = "Press ESC key to exit..."; + text_draw (c, screen, window, 10, HEIGHT - 10, text); + break; + } + case XCB_KEY_RELEASE: { + xcb_key_release_event_t *ev; + + ev = (xcb_key_release_event_t *)e; + + switch (ev->detail) { + /* ESC */ + case 9: + free (e); + xcb_disconnect (c); + return 0; + } + } + } + free (e); + } + } + + return 0; +} +- Interacting with the window manager
@@ -2097,9 +2387,7 @@ typedef struct { Id. Their type are xcb_atom_t:
-typedef struct { - uint32_t xid; -} xcb_atom_t; +typedef uint32_t xcb_atom_t;To change the property of a window, we use the following @@ -2659,9 +2947,7 @@ xcb_get_window_attributes_reply_t *xcb_get_window_attributes_reply (xcb_connecti In XCB, a color map is (as often in X) an Id:
-typedef struct { - uint32_t xid; -} xcb_colormap_t; +typedef uint32_t xcb_colormap_t;In order to access the screen's default color map, you just @@ -2902,19 +3188,14 @@ main () of X pixmap in XCB is an Id like a window:
-typedef struct { - uint32_t xid; -} xcb_pixmap_t; +typedef uint32_t xcb_pixmap_t;- In order to make the difference between a window and a pixmap, - XCB introduces a drawable type, which is a union + Like Xlib, there is no difference between a Drawable, a Window + or a Pixmap:
-typedef union { - xcb_window_t window; - xcb_pixmap_t pixmap; -} xcb_drawable_t; +typedef uint32_t xcb_drawable_t;in order to avoid confusion between a window and a pixmap. The @@ -3039,18 +3320,18 @@ xcb_void_cookie_t xcb_free_pixmap (xcb_connection_t *c, /* Pointer to the the function xcb_create_glyph_cursor:
-xcb_void_cookie_t xcb_create_glyph_cursor_checked (xcb_connection_t *c, - xcb_cursor_t cid, - xcb_font_t source_font, /* font for the source glyph */ - xcb_font_t mask_font, /* font for the mask glyph or XCB_NONE */ - uint16_t source_char, /* character glyph for the source */ - uint16_t mask_char, /* character glyph for the mask */ - uint16_t fore_red, /* red value for the foreground of the source */ - uint16_t fore_green, /* green value for the foreground of the source */ - uint16_t fore_blue, /* blue value for the foreground of the source */ - uint16_t back_red, /* red value for the background of the source */ - uint16_t back_green, /* green value for the background of the source */ - uint16_t back_blue) /* blue value for the background of the source */ +xcb_void_cookie_t xcb_create_glyph_cursor (xcb_connection_t *c, + xcb_cursor_t cid, + xcb_font_t source_font, /* font for the source glyph */ + xcb_font_t mask_font, /* font for the mask glyph or XCB_NONE */ + uint16_t source_char, /* character glyph for the source */ + uint16_t mask_char, /* character glyph for the mask */ + uint16_t fore_red, /* red value for the foreground of the source */ + uint16_t fore_green, /* green value for the foreground of the source */ + uint16_t fore_blue, /* blue value for the foreground of the source */ + uint16_t back_red, /* red value for the background of the source */ + uint16_t back_green, /* green value for the background of the source */ + uint16_t back_blue) /* blue value for the background of the source */TODO: Describe source_char @@ -3116,7 +3397,7 @@ uint32_t value_list; /* The cursor is already created */ mask = XCB_CWCURSOR; -value_list = cursor.xid; +value_list = cursor; xcb_change_window_attributes (conn, window, mask, &value_list);
@@ -3124,8 +3405,391 @@ xcb_change_window_attributes (conn, window, mask, &value_list);
- Complete example
- TODO: to do... + The following example displays a window with a + button. When entering the window, the window cursor is changed + to an arrow. When clicking once on the button, the cursor is + changed to a hand. When clicking again on the button, the + cursor window gets back to the arrow. The Esc key exits the + application.
++#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <xcb/xcb.h> + +#define WIDTH 300 +#define HEIGHT 150 + + + +static xcb_gc_t gc_font_get (xcb_connection_t *c, + xcb_screen_t *screen, + xcb_window_t window, + const char *font_name); + +static void button_draw (xcb_connection_t *c, + xcb_screen_t *screen, + xcb_window_t window, + int16_t x1, + int16_t y1, + const char *label); + +static void text_draw (xcb_connection_t *c, + xcb_screen_t *screen, + xcb_window_t window, + int16_t x1, + int16_t y1, + const char *label); + +static void cursor_set (xcb_connection_t *c, + xcb_screen_t *screen, + xcb_window_t window, + int cursor_id); + + +static void +button_draw (xcb_connection_t *c, + xcb_screen_t *screen, + xcb_window_t window, + int16_t x1, + int16_t y1, + const char *label) +{ + xcb_point_t points[5]; + xcb_void_cookie_t cookie_gc; + xcb_void_cookie_t cookie_line; + xcb_void_cookie_t cookie_text; + xcb_generic_error_t *error; + xcb_gcontext_t gc; + int16_t width; + int16_t height; + uint8_t length; + int16_t inset; + + length = strlen (label); + inset = 2; + + gc = gc_font_get(c, screen, window, "7x13"); + + width = 7 * length + 2 * (inset + 1); + height = 13 + 2 * (inset + 1); + points[0].x = x1; + points[0].y = y1; + points[1].x = x1 + width; + points[1].y = y1; + points[2].x = x1 + width; + points[2].y = y1 - height; + points[3].x = x1; + points[3].y = y1 - height; + points[4].x = x1; + points[4].y = y1; + cookie_line = xcb_poly_line_checked (c, XCB_COORD_MODE_ORIGIN, + window, gc, 5, points); + + error = xcb_request_check (c, cookie_line); + if (error) { + fprintf (stderr, "ERROR: can't draw lines : %d\n", error->error_code); + xcb_disconnect (c); + exit (-1); + } + + cookie_text = xcb_image_text_8_checked (c, length, window, gc, + x1 + inset + 1, + y1 - inset - 1, label); + error = xcb_request_check (c, cookie_text); + if (error) { + fprintf (stderr, "ERROR: can't paste text : %d\n", error->error_code); + xcb_disconnect (c); + exit (-1); + } + + cookie_gc = xcb_free_gc (c, gc); + error = xcb_request_check (c, cookie_gc); + if (error) { + fprintf (stderr, "ERROR: can't free gc : %d\n", error->error_code); + xcb_disconnect (c); + exit (-1); + } +} + +static void +text_draw (xcb_connection_t *c, + xcb_screen_t *screen, + xcb_window_t window, + int16_t x1, + int16_t y1, + const char *label) +{ + xcb_void_cookie_t cookie_gc; + xcb_void_cookie_t cookie_text; + xcb_generic_error_t *error; + xcb_gcontext_t gc; + uint8_t length; + + length = strlen (label); + + gc = gc_font_get(c, screen, window, "7x13"); + + cookie_text = xcb_image_text_8_checked (c, length, window, gc, + x1, + y1, label); + error = xcb_request_check (c, cookie_text); + if (error) { + fprintf (stderr, "ERROR: can't paste text : %d\n", error->error_code); + xcb_disconnect (c); + exit (-1); + } + + cookie_gc = xcb_free_gc (c, gc); + error = xcb_request_check (c, cookie_gc); + if (error) { + fprintf (stderr, "ERROR: can't free gc : %d\n", error->error_code); + xcb_disconnect (c); + exit (-1); + } +} + +static xcb_gc_t +gc_font_get (xcb_connection_t *c, + xcb_screen_t *screen, + xcb_window_t window, + const char *font_name) +{ + uint32_t value_list[3]; + xcb_void_cookie_t cookie_font; + xcb_void_cookie_t cookie_gc; + xcb_generic_error_t *error; + xcb_font_t font; + xcb_gcontext_t gc; + uint32_t mask; + + font = xcb_generate_id (c); + cookie_font = xcb_open_font_checked (c, font, + strlen (font_name), + font_name); + + error = xcb_request_check (c, cookie_font); + if (error) { + fprintf (stderr, "ERROR: can't open font : %d\n", error->error_code); + xcb_disconnect (c); + return -1; + } + + gc = xcb_generate_id (c); + mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT; + value_list[0] = screen->black_pixel; + value_list[1] = screen->white_pixel; + value_list[2] = font; + cookie_gc = xcb_create_gc_checked (c, gc, window, mask, value_list); + error = xcb_request_check (c, cookie_gc); + if (error) { + fprintf (stderr, "ERROR: can't create gc : %d\n", error->error_code); + xcb_disconnect (c); + exit (-1); + } + + cookie_font = xcb_close_font_checked (c, font); + error = xcb_request_check (c, cookie_font); + if (error) { + fprintf (stderr, "ERROR: can't close font : %d\n", error->error_code); + xcb_disconnect (c); + exit (-1); + } + + return gc; +} + +static void +cursor_set (xcb_connection_t *c, + xcb_screen_t *screen, + xcb_window_t window, + int cursor_id) +{ + uint32_t values_list[3]; + xcb_void_cookie_t cookie_font; + xcb_void_cookie_t cookie_gc; + xcb_generic_error_t *error; + xcb_font_t font; + xcb_cursor_t cursor; + xcb_gcontext_t gc; + uint32_t mask; + uint32_t value_list; + + font = xcb_generate_id (c); + cookie_font = xcb_open_font_checked (c, font, + strlen ("cursor"), + "cursor"); + error = xcb_request_check (c, cookie_font); + if (error) { + fprintf (stderr, "ERROR: can't open font : %d\n", error->error_code); + xcb_disconnect (c); + exit (-1); + } + + cursor = xcb_generate_id (c); + xcb_create_glyph_cursor (c, cursor, font, font, + cursor_id, cursor_id + 1, + 0, 0, 0, + 0, 0, 0); + + gc = xcb_generate_id (c); + mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT; + values_list[0] = screen->black_pixel; + values_list[1] = screen->white_pixel; + values_list[2] = font; + cookie_gc = xcb_create_gc_checked (c, gc, window, mask, values_list); + error = xcb_request_check (c, cookie_gc); + if (error) { + fprintf (stderr, "ERROR: can't create gc : %d\n", error->error_code); + xcb_disconnect (c); + exit (-1); + } + + mask = XCB_CW_CURSOR; + value_list = cursor; + xcb_change_window_attributes (c, window, mask, &value_list); + + xcb_free_cursor (c, cursor); + + cookie_font = xcb_close_font_checked (c, font); + error = xcb_request_check (c, cookie_font); + if (error) { + fprintf (stderr, "ERROR: can't close font : %d\n", error->error_code); + xcb_disconnect (c); + exit (-1); + } +} + +int main () +{ + xcb_screen_iterator_t screen_iter; + xcb_connection_t *c; + const xcb_setup_t *setup; + xcb_screen_t *screen; + xcb_generic_event_t *e; + xcb_generic_error_t *error; + xcb_void_cookie_t cookie_window; + xcb_void_cookie_t cookie_map; + xcb_window_t window; + uint32_t mask; + uint32_t values[2]; + int screen_number; + uint8_t is_hand = 0; + + /* getting the connection */ + c = xcb_connect (NULL, &screen_number); + if (!c) { + fprintf (stderr, "ERROR: can't connect to an X server\n"); + return -1; + } + + /* getting the current screen */ + setup = xcb_get_setup (c); + + screen = NULL; + screen_iter = xcb_setup_roots_iterator (setup); + for (; screen_iter.rem != 0; --screen_number, xcb_screen_next (&screen_iter)) + if (screen_number == 0) + { + screen = screen_iter.data; + break; + } + if (!screen) { + fprintf (stderr, "ERROR: can't get the current screen\n"); + xcb_disconnect (c); + return -1; + } + + /* creating the window */ + window = xcb_generate_id (c); + mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; + values[0] = screen->white_pixel; + values[1] = + XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_POINTER_MOTION; + cookie_window = xcb_create_window_checked (c, + screen->root_depth, + window, screen->root, + 20, 200, WIDTH, HEIGHT, + 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, + screen->root_visual, + mask, values); + cookie_map = xcb_map_window_checked (c, window); + + /* error managing */ + error = xcb_request_check (c, cookie_window); + if (error) { + fprintf (stderr, "ERROR: can't create window : %d\n", error->error_code); + xcb_disconnect (c); + return -1; + } + error = xcb_request_check (c, cookie_map); + if (error) { + fprintf (stderr, "ERROR: can't map window : %d\n", error->error_code); + xcb_disconnect (c); + return -1; + } + + cursor_set (c, screen, window, 68); + + xcb_flush(c); + + while (1) { + e = xcb_poll_for_event(c); + if (e) { + switch (e->response_type & ~0x80) { + case XCB_EXPOSE: { + char *text; + + text = "click here to change cursor"; + button_draw (c, screen, window, + (WIDTH - 7 * strlen(text)) / 2, + (HEIGHT - 16) / 2, text); + + text = "Press ESC key to exit..."; + text_draw (c, screen, window, 10, HEIGHT - 10, text); + break; + } + case XCB_BUTTON_PRESS: { + xcb_button_press_event_t *ev; + int length; + + ev = (xcb_button_press_event_t *)e; + length = strlen ("click here to change cursor"); + + if ((ev->event_x >= (WIDTH - 7 * length) / 2) && + (ev->event_x <= ((WIDTH - 7 * length) / 2 + 7 * length + 6)) && + (ev->event_y >= (HEIGHT - 16) / 2 - 19) && + (ev->event_y <= ((HEIGHT - 16) / 2))) + is_hand = 1 - is_hand; + + is_hand ? cursor_set (c, screen, window, 58) : cursor_set (c, screen, window, 68); + } + case XCB_KEY_RELEASE: { + xcb_key_release_event_t *ev; + + ev = (xcb_key_release_event_t *)e; + + switch (ev->detail) { + /* ESC */ + case 9: + free (e); + xcb_disconnect (c); + return 0; + } + } + } + free (e); + } + } + + return 0; +} +- Translation of basic Xlib functions and macros
@@ -3438,8 +4102,7 @@ default_screen = screen_of_display (c, screen_default_nbr); /* default_screen contains now the default root window, or a NULL window if no screen is found */
- RootWindow / RootWindowOfScreen -
-
+
xcb_connection_t *c; xcb_screen_t *screen; @@ -3529,7 +4192,7 @@ if (screen) { visual_iter = xcb_depth_visuals_iterator (depth_iter.data); for (; visual_iter.rem; xcb_visualtype_next (&visual_iter)) { - if (screen->root_visual.id == visual_iter.data->visual_id.id) { + if (screen->root_visual == visual_iter.data->visual_id) { visual_type = visual_iter.data; break; } @@ -3561,7 +4224,7 @@ if (screen) { uint32_t values[2]; gc = xcb_generate_id (c); - draw.window = screen->root; + draw = screen->root; mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND; values[0] = screen->black_pixel; values[1] = screen->white_pixel;