In the previous article, I showed how to connect the x server and how to create a window. Creating a window is fundamental to writing GUI programs. There are two other key points in GUI programming, one is event handling and the other is drawing in Windows. In this article, you will show how to use XCB to draw in a window.
Let's look at a sample code and how it works, with the following code:
1#include <stdlib.h>2#include <stdio.h>3 4#include <xcb/xcb.h>5 6 int7 Main ()8 {9 /*Geometric Objects*/Tenxcb_point_t points[] = { One{ +, +}, A{ +, the}, -{ the, +}, -{ the, the}}; the -xcb_point_t polyline[] = { -{ $, +}, -{ -, the},/*rest of points is relative*/ +{ -,- the}, -{ +, +}}; + Axcb_segment_t segments[] = { at{ -, +,560, -}, -{ the, -,520, -}}; - -xcb_rectangle_t rectangles[] = { -{ +, $, the, the}, -{ the, $, +, the}}; in -xcb_arc_t arcs[] = { to{ +, -, -, the,0, -<<6}, +{ the, -, -, the,0, the<<6}}; - the * /*Open the connection to the X server*/ $xcb_connection_t *connection =xcb_connect (null, NULL);Panax Notoginseng - /*Get The first screen*/ thexcb_screen_t *screen =Xcb_setup_roots_iterator (Xcb_get_setup (connection)). Data; + A /*Create Black (foreground) graphic context*/ thexcb_drawable_t window = screen->Root; +xcb_gcontext_t GC =xcb_generate_id (connection); -uint32_t mask = Xcb_gc_foreground |Xcb_gc_graphics_exposures; $uint32_t values[2] = {Screen->black_pixel,0}; $ - XCB_CREATE_GC (Connection, GC, window, mask, values); - the - /*Create a window*/Wuyiwindow =xcb_generate_id (connection); the -Mask = Xcb_cw_back_pixel |Xcb_cw_event_mask; Wuvalues[0] = screen->White_pixel; -values[1] =xcb_event_mask_exposure; About $Xcb_create_window (Connection,/*Connection*/ -Xcb_copy_from_parent,/*Depth*/ -Window/*window Id*/ -Screen->root,/*parent Window*/ A 0,0,/*x, y*/ + -, -,/*width, height*/ the Ten,/*Border_width*/ -Xcb_window_class_input_output,/*class*/ $Screen->root_visual,/*Visual*/ themask, values);/*Masks*/ the the the /*Map The window on the screen and flush*/ - Xcb_map_window (Connection, window); in Xcb_flush (connection); the the About /*Draw Primitives*/ thexcb_generic_event_t *Event; the while((Event=xcb_wait_for_event (connection))) { the Switch(Event->response_type & ~0x80) { + CaseXcb_expose: - /*We Draw the points*/ theXcb_poly_point (Connection, xcb_coord_mode_origin, window, GC,4, points);Bayi the /*We Draw the polygonal line*/ theXcb_poly_line (Connection, xcb_coord_mode_previous, window, GC,4, polyline); - - /*We Draw the segments*/ theXcb_poly_segment (Connection, window, GC,2, segments); the the /*Draw the rectangles*/ theXcb_poly_rectangle (Connection, window, GC,2, rectangles); - the /*Draw the Arcs*/ theXcb_poly_arc (Connection, window, GC,2, arcs); the 94 /*Flush the request*/ the Xcb_flush (connection); the the Break;98 default: About /*Unknown Event Type, ignore it*/ - Break;101 }102 103Free (Event);104 } the 106 return 0;107}
Operating effects such as:
Below, the GUI drawing of the above program analysis:
1, any drawing program, whether using the Win32 API, or Java Swing, can not be separated from the concept of GC and DC, the use of XCB Programming window program is the same. These two concepts, one represents the figure how to paint, and one represents the plot where. Because you need to specify too much information when drawing, such as the thickness of the brush, line style, foreground color, background color, and so on, if you pass this information as a parameter to the drawing function, it will produce two questions: first, calling these functions is too complex, the second is inefficient. So now all the mainstream GUI libraries have adopted a consistent approach, that is to organize this information into a context, which we call graphic context, can be referred to as Gcontext or GC. A DC can be thought of as the canvas used for drawing, we can draw the diagram directly onto the screen, or we can draw it into the window, and of course, it can also be drawn into the control (because the nature of the control is also the window). In object-oriented programming languages, the components that can be drawn are often inherited from drawable. In XCB, you can see from the signature of the drawing function that it still calls the target of the drawing drawable, although it is just an ID.
2, when to draw. In theory, a drawing function can be called at any time. In practice, however, all GUI programs invoke the drawing function in the event that the window is redrawn. Window redraw events, some called OnPaint, some called ondraw,xcb in the more strange, called expose. Whatever it is called, the truth is the same. That is, the event is triggered when the window is first displayed, from hidden to displayed, or when the window content needs to be refreshed, so it is best to call the drawing function in the code that handles the event, both to ensure that we see the result of the drawing and to be efficient (the drawing function is not executed when the window is not visible, The drawing function does not have to be executed when the window does not change). The MVC pattern is also built on the basis of separating the data from the display, the data can be manipulated at any time, but the drawing only occurs when the window is redrawn.
3, call the drawing function. This does not need to be said, because almost all of the drawing functions are self-explanatory, and when you see the function name, you know what it is going to do.
In XCB, creating a GC can be done through the XCB_CREATE_GC () function, and the creation window can be done through the Xcb_create_window () function. In both of these functions, there is a strange pattern, that is, a mask and value array to set the GC and window specific information. In the previous article, the created window has no background, and in this case, the window has a white background, because Xcb_cw_back_pixel is specified in its mask parameter when Xcb_create_window is called here.
With the help of Ctags and Vim's Taglist.vim plug-in, it is very easy to see the values of these masks and their meanings, just press CTRL +] to jump to the corresponding definition. The following two graphs are a series of xcb_gc_*** defined in enum xcb_gc_t:
The following two graphs are the mask values that can be used to create a window:
These enumerations have very detailed comments, so I'm not here to nag. The comments in LIBXCB's header file are a good learning material in itself, aren't they?
(Jingshan Ranger in 2014-07-05 published in the blog Park, reproduced please indicate the source. )