Tutoriál grafiky pomocí Xlib Projekt do GZN
Radek Brich Fakulta informaˇcních technologií Vysoké uˇcení technické v Brneˇ
2006
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
1 / 26
X Window System (1)
Historie 1984 – poˇcátek vývoje. 1985 – verze 9 – licence MIT. 1987 – vychází verze 11.
Architektura klient–server Server kreslí na obrazovku a cˇ te vstup od uživatele. Klient urˇcuje, co kreslit a zpracovává vstup od uživatele. Sít’ová transparence.
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
2 / 26
X Window System (2)
Hierarchie oken Koˇrenové okno (root) – celá obrazovka. Okna nižších úrovní patˇrí aplikacím. O správu oken první úrovneˇ se stará speciální program – Window Manager. ˇ S okny dalších úrovní muže ˚ aplikace nakládat libovolne.
Každá událost je propagována hierarchií oken nahoru dokud není zpracována.
Klient se serverem komunikuje standardním X protokolem. Ten je implementován v knihovneˇ Xlib.
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
3 / 26
Knihovna Xlib
Vrstva mezi X protokolem a aplikací. Obsahuje funkce pro komunikaci s X serverem – práce s okny, zpracování událostí, jednoduché kreslení. Xlib má být maximálneˇ univerzální – nepodporuje žádné prvky uživatelského rozhraní. Další vrstva nad Xlib – knihovny nástroju. ˚ Motif, GTK, Qt, . . . Obsahují sadu objektu˚ pro tvorbu uživatelského rozhraní a další pomocné funkce. Pomáhají tvoˇrit jednotný vzhled aplikací.
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
4 / 26
Pˇríklad – Minimální X klient
Následuje ukázka jednoduchého programu s Xlib, který se pˇripojí k X serveru, vytvoˇrí a zobrazí okno, ˇ cˇ áru. nakreslí do nej
Program naleznete v souboru xlib-minimal.c, pˇriložen je také Makefile. Pˇri pˇrekladu v gcc je nutno pˇrilinkovat knihovnu X11: gcc xlib-minimal.c -o xlib-minimal -lX11
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
5 / 26
Pˇripojení k X serveru Display *XOpenDisplay(char *display_name) Parametr display_name identifikuje libovolný display v síti, napˇr. "jmeno.pocitace.dom:0". ˇ Lze pˇredat také NULL, pak se použije obsah promenné prostˇredí DISPLAY. #include <stdio.h> #include <X11/Xlib.h> int main() { Display *display = XOpenDisplay(NULL); if (display == NULL) { fprintf(stderr, "Cannot connect to X server."); return(-1); } XCloseDisplay(display); return 0; } Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
6 / 26
Vytvoˇrení okna Objekt okna se vytváˇrí funkcí XCreateWindow (mnoho parametru) ˚ nebo XCreateSimpleWindow (méneˇ parametru). ˚ XMapWindow okno zobrazí. int screen = DefaultScreen(display); int black = BlackPixel(display, screen); int white = WhitePixel(display, screen); Window window = XCreateSimpleWindow( display, /* display */ DefaultRootWindow(display), /* parent window */ 0, 0, /* x, y */ 160, 100, /* width, height */ 0, /* border_width */ black, black /* border color, background */ ); XMapWindow(display, window);
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
7 / 26
Grafický kontext (1)
Grafický kontext (GC) obsahuje ruzné ˚ parametry kreslení. Vytvoˇríme grafický kontext s bílou barvou popˇredí: GC gc = XCreateGC(display, window, /* drawable */ 0, /* valuemask */ NULL); /* values[] */ XSetForeground(display, gc, white_pixel);
Nebo s použitím posledních dvou parametru: ˚ XGCValues values = { .foreground=white_pixel }; GC gc = XCreateGC(display, window, GCForeground, &values);
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
8 / 26
Grafický kontext (2) Pro všechny atributy GC existují pˇríslušné funkce: XSetForeground, XSetBackground, XSetLineAttributes, XSetDashes, XSetFont, . . . Atributy cˇ áry (XSetLineAttributes): line_width – tloušt’ka line_style – styl LineSolid (plná cˇ ára) LineOnOffDash (stˇrídání barva/nic) LineDoubleDash (barva popˇredí/pozadí)
cap_style – zakonˇcení cˇ áry CapButt (kolmé) CapNotLast (pˇri tloušt’ce 1 pixel se poslední bod nekreslí) CapRound (zakulacený konec) CapProjecting (prodloužení o polovinu tloušt’ky cˇ áry)
join_style – zpusob ˚ navázání cˇ áry JoinMiter (ostré) JoinRound (kulaté) JoinBevel (setnuté) Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
9 / 26
Smyˇcka událostí Události si musíme od X Serveru vyžádat funkcí XSelectInput. Expose je zaslán vždy pˇri ztráteˇ cˇ ásti obsahu okna – požadavek na pˇrekreslení.
XSelectInput(display, window, ExposureMask); XEvent event; while (1) { XNextEvent(display, &event); switch (event.type) { case Expose: xlib-minimal.c if (event.xexpose.count > 0) break; XDrawLine(display, window, gc, 10, 20, 150, 80); XFlush(display); break; } } Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
10 / 26
Kreslící funkce Bod XDrawPoint(display, drawable, gc, x, y)
ˇ Cára XDrawLine(display, drawable, gc, x1, y1, x2, y2)
ˇ Oblouk – jednotkou pro zadávání úhlu je 1/64 stupne. XDrawArc(display, drawable, gc, x, y, width, height, angle1, angle2)
Obdélník XDrawRectangle(display, drawable, gc, x, y, width, height)
Text XDrawString(display, drawable, gc, x, y, char *string, length)
Dále varianty: XDrawPoints, XDrawLines, XDrawArcs, . . . XDrawString16, XDrawImageString (kreslí navíc pozadí), . . .
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
11 / 26
ˇ program - malování Složitejší
Nyní program rozšíˇríme: podokna a další události, více barev, výpis textu.
Výsledný program je k dispozici v souboru xlib-scrawl.c.
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
12 / 26
Další události Klávesnice: KeyPress, KeyRelease (maska pro XSelectInput: KeyPressMask, KeyReleaseMask). Myš: ButtonPress, ButtonRelease (ButtonPressMask, ButtonReleaseMask), MotionNotify (PointerMotionMask, ButtonMotionMask – pohyb myší se stisknutým tlaˇcítkem, ˇ konkrétního tlaˇcítka, Button1MotionMask – výber ˇ stav PointerMotionHintMask – poslat událost jen když se zmení tlaˇcítek). ˇ rení okna myší cˇ i klávesnicí: EnterNotify, LeaveNotify Zameˇ (EnterWindowMask, LeaveWindowMask), FocusIn, FocusOut (FocusChangeMask). ˇ Zmena stavu okna – pozice, velikost, rámeˇcek, vrstva: ConfigureNotify (StructureNotifyMask).
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
13 / 26
Okno pro kreslení (1) Vytvoˇríme si podokno, do kterého se bude kreslit. Window canvas = XCreateSimpleWindow(display, window, ..., 1 /*border_width*/, white_pixel /*border*/, black_pixel /*bground*/);
ˇ události od myši – pˇri stisknutém tlaˇcítku Vyžádáme si pro nej ˇ budeme kreslit cˇ áry mezi dvema posledními pozicemi myši. XSelectInput(display, canvas, ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | ExposureMask); XMapWindow(display, canvas);
Také vytvoˇríme další GC pro kreslení do tohoto okénka. GC canvas_gc = XCreateGC(display, canvas, 0, NULL); XSetForeground(display, canvas_gc, white_pixel);
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
14 / 26
Okno pro kreslení (2) int prev_x = -1, prev_y; switch (event.type) ... case ButtonPress: case ButtonRelease: case MotionNotify: if (event.xbutton.window == canvas) { int x = event.xbutton.x; int y = event.xbutton.y; if (prev_x > 0) XDrawLine(display, canvas, canvas_gc, prev_x, prev_y, x, y); if (event.type == ButtonRelease) prev_x = -1; else { prev_x = x; prev_y = y; } XFlush(display); break; } ... Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
15 / 26
Pixmapy (1)
Nyní po zakrytí a následném odkrytí okna nakreslené cˇ áry mizí. ˇ Rešení problému – kreslit paralelneˇ také do pixmapy. Do pixmapy lze kreslit stejným zpusobem ˚ jako do okna, její obsah je ale X Serverem vždy udržován. Pˇri události Expose budeme kopírovat pˇríslušnou cˇ ást pixmapy do okna canvas.
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
16 / 26
Pixmapy (2) Pixmap canvas_pixmap = XCreatePixmap(display, canvas, 800 /*width*/, 600 /*height*/, DefaultDepth(display, screen)); ... case Expose: if (event.xexpose.window == canvas) { int x = event.xexpose.x; int y = event.xexpose.y; XCopyArea(display, canvas_pixmap /*src*/, canvas /*dest*/, gc, x, y, /* src x, y */ event.xexpose.width, event.xexpose.height, /* src w, h */ x, y /* dest x, y */); } ... case ButtonPress: case ButtonRelease: case MotionNotify: ... XDrawLine(display, canvas, canvas_gc, prev_x, prev_y, x, y); XDrawLine(display, canvas_pixmap, canvas_gc, prev_x, prev_y, x, y); ...
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
17 / 26
Alokace barev
Barva se vybírá z 48-bitového rozsahu. Funkce XAllocColor pˇriˇradí pixelu nejbližší barvu, která je k dispozici. XFreeColors uvolní nepoužívané barvy z palety. Colormap colormap = DefaultColormap(display, screen); XColor green = {.red=0x0000, .green=0xFFFF, .blue=0x0000}; XAllocColor(display, colormap, &green); XFreeColors(display, colormap, &green.pixel /* pixels[] */, 1 /* npixels */, 0 /* planes */);
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
18 / 26
Fonty a text ˇ ˇ Font je identifikován ˇretezcem s parametry fontu. Takový ˇretezec lze vytvoˇrit programem xselfont. Napˇríklad Helvetica s cˇ eským kódováním o velikosti 12 bodu: ˚ "-*-helvetica-medium-r-*-12-*-iso8859-2" Font font = XLoadFont(display, "-*-helvetica-medium-r-*-12-*"); XSetFont(display, gc, font); ... case Expose: /* main window */ if (event.xexpose.window == window) { char *s = "Line width:"; XSetForeground(display, gc, white_pixel); XDrawString(display, window, gc, 10, 20, s, strlen(s)); }
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
19 / 26
Atributy okna (1)
Každému oknu lze nastavit ruzné ˚ atributy (pozadí, rámeˇcek, gravitace, maska událostí, kurzor a další). Atributy se oknu nastaví bud’ pˇrímo pˇri vytvoˇrení funkcí ˇ pomocí XChangeWindowAttributes. XCreateWindow nebo pozdeji Události lze také vybrat funkcí XSelectInput. Struktura XSetWindowAttributes obsahuje všechny atributy okna ˇ – ty, které chceme skuteˇcneˇ zmenit, urˇcíme maskou. Pˇríklad: XSetWindowAttributes attributes = { .win_gravity = SouthWestGravity }; XChangeWindowAttributes(display, window, CWWinGravity, &attributes);
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
20 / 26
Atributy okna (2) Vybrané atributy (v závorce pˇríslušná maska): background_pixmap (CWBackPixmap), background_pixel (CWBackPixel), border_pixmap (CWBorderPixmap), border_pixel (CWBorderPixel) ˇ eˇ bit_gravity (CWBitGravity) – kde zustane ˚ obsah okna pˇri zmen jeho velikosti (implicitneˇ ForgetGravity – zapomene se), ˇ eˇ win_gravity (CWWinGravity) – kam se pˇresune okno pˇri zmen velikosti rodiˇce backing_store (CWBackingStore) – udržování obsahu okna na straneˇ X Serveru, save_under (CWSaveUnder) – pro pop-up okna, pamatují se pixely zakryté tímto oknem event_mask (CWEventMask) – množina událostí, které okno pˇrijímá, do_not_propagate_mask (CWDontPropagate) – množina událostí, které se nemají pˇredávat rodiˇci colormap (CWColormap), cursor (CWCursor) Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
21 / 26
Další parametry okna (1)
Každému oknu lze pˇriˇradit jméno: XStoreName(display, window, "Scrawl"); U prvního programu nebylo ukonˇcení cˇ isté – pokud uživatel zavˇrel okno, program byl jednoduše zabit window managerem. ˇ Rešení – vyžádat si od WM událost WM_DELETE_WINDOW. WM pak jen pošle tuto událost a pˇredpokládá, že se program o likvidaci daného okna postará sám. Atom delete_window = XInternAtom(display, "WM_DELETE_WINDOW", 1); XSetWMProtocols(display, window, &delete_window, 1);
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
22 / 26
Další parametry okna (2) WM nemá rezervovány speciální události – používá událost ClientMessage (komunikace mezi klienty). int alive = 1; while (alive) { XNextEvent(display, &event); switch (event.type) { ... case ClientMessage: if (event.xclient.data.l[0] == delete_window) alive = 0; /* exit program */ break; ... } } XDestroyWindow(display, window); XCloseDisplay(display);
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
23 / 26
Výsledný program
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
24 / 26
ˇ Záver Hotový program má po pˇreložení 15 kB :-) Xlib je nutné použít pro psaní Window Manageru a nových ˇ ˇ toolkitu. ˚ Psát bežné programy pˇrímo v Xlibu se vetšinou nevyplatí. . . Budoucnost: XCB (X C Binding) – nový projekt (2001), jeho cílem je nahradit Xlib. menší komplexita a velikost knihovny ˇ blíže k protokolu X11 nižší úroven, ˇ pro PDA apod. vhodnejší
Implementace X-Serveru: X.org (puvodn ˚ eˇ XFree86) – pro unixové systémy. Xming, Cygwin/X – X Server pro Microsoft Windows X11.app – implementace X Serveru obsažená v MacOS X (založena na XFree86)
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
25 / 26
Literatura
The Xlib Manual Dodáván v distribuci X Window System, HTML verze zde: http://tronche.com/gui/x/xlib/ Xlib Programming Manual (O’Reilly & Associates, Inc.) http://www.sbin.org/doc/Xlib/ Wikipedia http://en.wikipedia.org/wiki/Xlib http://en.wikipedia.org/wiki/X_Window_System
Radek Brich (FIT VUT Brno)
Tutoriál grafiky pomocí Xlib
2006
26 / 26