<<
Home , XCB

Jest to program, który nic nie robi, nawi ązuje tylko poł ączenie z X serwerem i od razu porzuca je, bez sprawdzenia GRAFIKA KOMPUTEROWA poprawno ści wykonania si ę operacji. Nie daje on żadnych wizualnych efektów. Nale ży podkre śli ć, że pusty ła ńcuch ("") Podstawy programowania w środowisku X Window jako argument funkcji XOpenDisplay oznacza u życie takiego wy świetlacza jaki jest zdefiniowany przez zmienn ą systemow ą DISPLAY. Budowa systemu X Window Kompilacji i konsolidacji takiego programu umieszczonego w pliku „prog.” dokona ć mo żna poleceniem: gcc -o prog -I/usr/X11R6/include -L/usr/X11R6/lib \ -R/usr/X11R6/lib -lX11 prog.c Gdzie -o - okre ślenie nazwy pliku z programem wykonywalnym (tutaj: „prog”), -I - okre ślenie poło żenia zbiorów nagłówkowych, -L - okre ślenie poło żenia bibliotek, -R - okre ślenie poło żenia bibliotek doł ączanych dynamicznie (dopiero podczas działania programu), -l - okre ślenie doł ączanych bibliotek. Pomini ęcie opcji -I, -L, -R spowoduje wykorzystanie ustawie ń ze zmiennej systemowej LD_LIBRARY_PATH. Podstawowe konstrukcje programistyczne w środowisku X Window - program przykładowy Poni ższy program wy świetla okno z napisem. Wyj ście z programu nast ępuje w wyniku naci śni ęcia klawisza „q”. Dyrektywy i definicje: X był od samego pocz ątku projektowany jako system zorientowany sieciowo. Serwer odpowiada głównie za #include wy świetlanie grafiki, obsług ę myszy, czy klawiatury. Wszelkie aplikacje X s ą klientami z korzystaj ącymi z funkcji #include ę ą ę ć udost pnianych przez serwer. Klienci mog si znajdowa na tej samej maszynie co serwer lub na zupełnie innej. #define TRUE 1 Komunikacja pomi ędzy klientami a serwerem odbywa si ę zgodnie z protokołem X. Aplikacje-klienci wysyłaj ą do #define FALSE 0 serwera komunikaty w stylu "prosz ę, narysuj mi okno o takich współrz ędnych". Serwer natomiast powiadamia klienta o Plik nagłówkowy .h zawiera daklaracj ę funkcji i struktur danych Xlib, natomiast Xutil.h u żywany jest przez funkcje zdarzeniach typu naci śni ęcie klawisza myszki przez u żytkownika. użytkowe Xlib.

Application Stałe ła ńcuchowe: X Toolkit char hello[]="To jest okno"; Xt Intrinsics char NazwaIkony[]="Ikona"; char NazwaOkna[]="Okno"; Xlib, XCB Program główny (argc - liczba argumentów linii polecenia, argv - tablica wskaza ń do tych argumentów): X protocol main(int argc, char *argv[]){ Deklaracja zmiennych - najpierw wska źnik definiuj ący wy świetlacz do którego wysyłamy dane - dany X serwer: Najni ższym poziomem jest X protocol okre ślaj ący standard przesyłania danych pomi ędzy klientem i serwerem. Display *wyswietlacz; Nast ępny poziom odpowiedzialny jest za operacje na oknach, klawiaturze i myszy. Mo że by ć one realizowany za Zmienna odpowiedzialna za nasze okno: po średnictwem biblioteki Xlib (jak w przypadku naszego ćwiczenia) lub nowszej XCB , która w przeciwie ństwie do Window okno; starszej wersji umo żliwia asynchroniczn ą komunikacj ę z serwerem. Kolejnym poziomem jest poziom Xt Intrinsics Struktura zawieraj ące informacje o parametrach graficznych, niezb ędna dla wszystkich elementów, które chcemy umo żliwiaj ący korzystanie ze standardowych bloków takich jak menu, przyciski, suwaki, okna dialogowe itp. rysowa ć - kontekst graficzny: Najwy ższym poziomem jest poziom X Toolkit uzale żniony od producenta - najpopularniejsze środowiska to , GC graficznykontekst; Gtk+ czy . Struktura do zapisywania zdarze ń: XEvent zdarzenie; Praca z j ęzykiem C i bibliotekami X Window Informacja o stanie klawiatury: Pliki nagłówkowe zawieraj ą zwykle wymagane deklaracje obiektów (zmiennych, funkcji, ...) zdefiniowanych w plikach KeySym klawisz; bibliotecznych doł ączanych do programu w fazie konsolidacji. Niezb ędne dla nas pliki znajduj ą si ę w podkatalogach Parametry takie jak rozmiar i poło żenie okna (definicja znajduje si ę w Xutli.h): „X11” umieszczonych w katalogach „/usr/X11R6/lib” (pliki biblioteczne) i „/usr/X11R6/include” (pliki nagłówkowe). XSizeHints info; Najprostszy program pracuj ący w środowisku X Window wygl ąda nast ępuj ąco: Numer u żywanego ekranu: int ekran; #include Kolory tła i pierwszego planu: main(int argc, char *argv[]) unsigned long pierwszyplan, tlo; { Bufor do zapami ętywania znaków z klawiatury: Display *wyswietlacz; char bufor[8]; wyswietlacz = XOpenDisplay(""); Licznik klawiszy: XCloseDisplay(wyswietlacz); int liklawiszy; } Zmienna do kontrolowania momentu zako ńczenia programu: int zakoncz; Zdarzenie Expose: case Expose: Pocz ątek programu: Warto ść pola xexpose.count równa zero mo że oznacza ć dwie mo żliwo ści: tylko jedno zdarzenie Expose miało miejsce, albo jest to ostatnie zdarzenie z grupy zdarze ń typu Expose: Otwarcie poł ączenia z X serwerem, parametr "" oznacza, że wy świetlacz ma by ć ustawiony na podstawie zmiennej if (zdarzenie.xexpose.count == 0){ systemowej DISPLAY, mo żna te ż poda ć konkretny komputer: Narysowanie zawarto ści okna - w naszym przypadku sprowadza si ę ono do wypisania funkcj ą XDrawImageString tekstu wyswietlacz = XOpenDisplay(""); zawartego w zmiennej hello. Parametrami tej funkcji są: wy świetlacz, okno (uchwyt), kontekst graficzny, poło żenie Pobranie numeru domy ślnego ekranu (w naszym przypadku i tak jest to tylko jeden ekran o numerze 0): napisu (pierwszej litery) w oknie, napis i jego długo ść . W naszym programie mamy do czynienia tylko z jednym oknem ekran = DefaultScreen(wyswietlacz); i mo żna by było zarówno wy świetlacz jak i okno poda ć normalnie. Bezpieczniej jest jednak odczyta ć z pól rekordu o Makra WhitePixel i BlackPiksel zwracaj ą odpowiednie warto ści liczbowe opisuj ące kolor biały i czarny dla naszego nazwie zdarzenie, o który wy świetlacz i o które okno chodzi w danym zdarzeniu: wy świetlacza, u żytkownik ma dzi ęki temu pewno ść , że b ędą to odpowiednio kolor biały i czarny bez wzgl ędu na XDrawImageString(zdarzenie.xexpose.display, maksymaln ą ilo ść kolorów, ilo ść bitów na piksel itp.: zdarzenie.xexpose.window, graficznykontekst, 105, 65, tlo = WhitePixel(wyswietlacz, ekran); hello, strlen(hello));} pierwszyplan = BlackPixel(wyswietlacz, ekran); Break oznacza koniec akcji dla zdarzenia Expose: Ustawienie parametrów okna poprzez wpisanie ich do struktury info. Pola x, y tej struktury opisuj ą poło żenie górnego break; lewego rogu okna; pola width i hight okre ślaj ą szeroko ść i wysoko ść okna; pole flags informuje, które z pól tej struktury Kolejne zdarzenie to zdarzenie informuj ące o zmianach układu klawiatury - "konfiguracji": zostały zdefiniowane. Odpowiednie funkcje mog ą modyfikowa ć t ę struktur ę: case MappingNotify: info.x = 100; Chc ąc zabezpieczy ć si ę przed tak ą zmian ą nale ży zawrze ć w programie nast ępuj ącą instrukcj ę: info.y = 150; XRefreshKeyboardMapping(&zdarzenie); info.width = 275; Koniec akcji dla zdarzenia MappingNotify: info.height = 120; break; info.flags = PPosition | PSize; Wreszcie zdarzenie zwi ązane z naci śni ęciem klawiszy Stworzenie okna. Nie powoduje ono wy świetlenia okna, a jedynie stworzenie odpowiednich struktur danych. case KeyPress: Parametrami funkcji tworz ącej okno s ą: wy świetlacz, na którym ma by ć stworzone okno, okno rodzic (dokładniej: jego Konwersja naci śni ętych klawiszy na ła ńcuch znaków. Funkcja XLookupString zwraca informacje o długo ści tego uchwyt) - w naszym przykładzie jest nim pulpit (okno domy ślne), poło żenie i rozmiary, grubo ść ramki (7) i wreszcie ła ńcucha - zazwyczaj jest to warto ść jeden. kolorystyka okna. Stworzone okno identyfikowane jest pó źniej przez wy świetlacz i uchwyt (numer) okna: liklawiszy = XLookupString(&zdarzenie, bufor, 8, &klawisz, 0); okno = XCreateSimpleWindow(wyswietlacz, Je śli był to wła śnie tylko jeden klawisz i był to w dodatku klawisz „q”, to nale ży zako ńczy ć program: DefaultRootWindow(wyswietlacz), if ((liklawiszy == 1) && (bufor[0] == 'q')) info.x, info.y, info.width, info.height, zakoncz = TRUE; 7, pierwszyplan, tlo); Koniec instrukcji switch i koniec p ętli: Okre ślenie własno ści okna takich jak: nazwa okna, nazwa ikony, wska źnik na map ę bitow ą definiuj ącą ikon ę (tu None), } liczba i parametry wołania programu oraz dane zawarte w strukturze info: } XSetStandardProperties(wyswietlacz, okno, NazwaOkna, Przed zako ńczeniem programu nale ży jeszcze wykonać: NazwaIkony, None, argv, argc, &info); Wyczyszczenie i zwolnienie pami ęci potrzebnej na kontekst graficzny: Utworzenie kontekstu graficznego z warto ściami domy ślnymi (0, 0) dla okre ślenia maski i warto ści: XFreeGC(wyswietlacz, graficznykontekst); graficznykontekst = XCreateGC(wyswietlacz, okno, 0, 0); Usuni ęcie okna: Wpisanie do kontekstu graficznego informacji o kolorze pierwszego planu i tła: XDestroyWindow(wyswietlacz, okno); XSetBackground(wyswietlacz, graficznykontekst, tlo); Zamkni ęcie poł ączenia z wy świetlaczem: XSetForeground(wyswietlacz, graficznykontekst, pierwszyplan); XCloseDisplay(wyswietlacz); Wybór zdarze ń, które maj ą by ć sygnalizowane naszemu oknu. Nas interesuje tylko naci śni ęcie klawisza, potrzebne do Koniec programu: zako ńczenia programu, oraz zdarzenie Expose, pojawiaj ące si ę w przypadku konieczno ści odrysowania okna (gdy np. } dzi ęki zamkni ęciu jakiego ś okna nasze okno zostało odsłoni ęte): XSelectInput(wyswietlacz, okno, (KeyPressMask | ExposureMask)); Wy świetlenie stworzonego okna na wierzchu wszystkich okien: XMapRaised(wyswietlacz, okno) ; Ustawienie zmiennej ko ńcz ącej program: zakoncz = FALSE; Pętla, a ż zmienna zakoncz nie zmieni warto ści (warto zwróci ć uwag ę na podwójny znak równo ści): while (zakoncz == FALSE){ Pobranie kolejnego zdarzenia. Funkcja ta czeka, a ż nie pojawi si ę jedno ze zdarze ń okre ślonych funkcj ą XSelectInput: XNextEvent(wyswietlacz, &zdarzenie); Wykonanie akcji w zale żno ści od typu zdarzenia (odpowiada instrukcji CASE w Pascalu): switch(zdarzenie.type){ Kod programu przykładowego graficznykontekst, 105, 65, #include hello, strlen(hello)); #include break; #define TRUE 1 case MappingNotify : #define FALSE 0 XRefreshKeyboardMapping(&zdarzenie); break; char hello[]="To jest okno"; case KeyPress: char NazwaIkony[]="Ikona"; liklawiszy = XLookupString(&zdarzenie, bufor, 8, char NazwaOkna[]="Okno"; &klawisz, 0); if ((liklawiszy == 1) && (bufor[0] == 'q')) main(int argc, char *argv[]){ zakoncz = TRUE; Display *wyswietlacz; } Window okno; } GC graficznykontekst; XFreeGC(wyswietlacz, graficznykontekst); XEvent zdarzenie; XDestroyWindow(wyswietlacz, okno); KeySym klawisz; XCloseDisplay(wyswietlacz); XSizeHints info; } int ekran; Wybrane stałe i funkcje biblioteczne int zakoncz; XSetLineAttributes ( wyswietlacz = XOpenDisplay(""); Display* /* display */, ekran = DefaultScreen(wyswietlacz); GC /* gc */, unsigned long pierwszyplan, tlo; unsigned int /* line_width */, char bufor[8]; int /* line_style */, int liklawiszy; int /* cap_style */, tlo = WhitePixel(wyswietlacz, ekran); int /* join_style */ pierwszyplan = BlackPixel(wyswietlacz, ekran); ); info.x = 100; info.y = 150; /* LineStyle */ info.width = 275; info.height = 120; #define LineSolid 0 info.flags = PPosition | PSize; #define LineOnOffDash 1 okno = XCreateSimpleWindow(wyswietlacz, #define LineDoubleDash 2 DefaultRootWindow(wyswietlacz), info.x, info.y, info.width, info.height, 7, /* capStyle */ pierwszyplan, tlo); XSetStandardProperties(wyswietlacz, okno, NazwaOkna, NazwaIkony, #define CapNotLast 0 None, argv, argc, &info); #define CapButt 1 graficznykontekst = XCreateGC(wyswietlacz, okno, 0, 0); #define CapRound 2 XSetBackground(wyswietlacz, graficznykontekst, tlo); #define CapProjecting 3 XSetForeground(wyswietlacz, graficznykontekst, pierwszyplan); XSelectInput(wyswietlacz, okno, (KeyPressMask | ExposureMask)); /* joinStyle */ XMapRaised(wyswietlacz, okno); zakoncz = FALSE; #define JoinMiter 0 #define JoinRound 1 while (zakoncz == FALSE){ #define JoinBevel 2 XNextEvent(wyswietlacz, &zdarzenie); switch(zdarzenie.type){ case Expose: if (zdarzenie.xexpose.count == 0) XDrawImageString(zdarzenie.xexpose.display, zdarzenie.xexpose.window, typedef struct { int /* y1 */, short x, y; int /* x2 */, } XPoint ; int /* y2 */ ); typedef struct { short x1, y1, x2, y2; extern XDrawLines ( } XSegment ; Display* /* display */, Drawable /* */, extern XDrawArc ( //ew. XFillArc GC /* gc */, Display* /* display */, XPoint* /* points */, Drawable /* d */, int /* npoints */, GC /* gc */, int /* mode */ Int /* x */, ); Int /* y */, unsigned int /* width */, extern XDrawPoint ( unsigned int /* height */, Display* /* display */, int /* angle1 */, Drawable /* d */, int /* angle2 */ GC /* gc */, ); int /* x */, int /* y */ extern XDrawArcs ( ); Display* /* display */, Drawable /* d */, extern XDrawPoints ( GC /* gc */, Display* /* display */, XArc* /* arcs */, Drawable /* d */, int /* narcs */ GC /* gc */, ); XPoint* /* points */, int /* npoints */, extern XDrawImageString ( int /* mode */ Display* /* display */, ); Drawable /* d */, GC /* gc */, extern XDrawRectangle ( // XFillRectangle int /* x */, Display* /* display */, int /* y */, Drawable /* d */, _Xconst char* /* string */, GC /* gc */, int /* length */ int /* x */, ); int /* y */, unsigned int /* width */, extern XDrawImageString16 ( unsigned int /* height */ Display* /* display */, ); Drawable /* d */, GC /* gc */, extern XDrawRectangles ( int /* x */, Display* /* display */, int /* y */, Drawable /* d */, _Xconst XChar2b* /* string */, GC /* gc */, int /* length */ XRectangle* /* rectangles */, ); int /* nrectangles */ ); extern XDrawLine ( Display* /* display */, extern XDrawSegments ( Drawable /* d */, Display* /* display */, GC /* gc */, Drawable /* d */, int /* x1 */, GC /* gc */, XSegment* /* segments */, int bitmap_bit_order; /* LSBFirst, MSBFirst */ int /* nsegments */ int bitmap_pad; /* 8, 16, 32 either XY or ZPixmap */ ); int depth; /* depth of image */ int bytes_per_line; /* accelarator to next line */ extern XDrawString ( int bits_per_pixel; /* bits per pixel (ZPixmap) */ Display* /* display */, unsigned long red_mask; /* bits in z arrangment */ Drawable /* d */, unsigned long green_mask; GC /* gc */, unsigned long blue_mask; int /* x */, XPointer obdata; /* hook for the object routines to hang on*/ int /* y */, struct funcs { /* image manipulation routines */ _Xconst char* /* string */, struct _XImage *(*create_image)(); int /* length */ int (*destroy_image) (struct _XImage *); ); unsigned long (*get_pixel) (struct _XImage *, int, int); int (*put_pixel) (struct _XImage *, int, int, unsigned long); extern XDrawString16 ( struct _XImage *(*sub_image)(struct _XImage *, int, int, Display* /* display */, unsigned int, unsigned int); Drawable /* d */, int (*add_pixel) (struct _XImage *, long); GC /* gc */, } f; int /* x */, } XImage ; int /* y */, _Xconst XChar2b* /* string */, /* int /* length */ * These macros are used to give some to the image routines ); * so tha naive people are more comfortable with them. */ extern XDrawText ( #define XDestroyImage (ximage) \ Display* /* display */, ((*((ximage)->f.destroy_image))((ximage))) Drawable /* d */, #define XGetPixel (ximage, x, y) \ GC /* gc */, ((*((ximage)->f.get_pixel))((ximage), (x), (y))) int /* x */, #define XPutPixel (ximage, x, y, pixel) \ int /* y */, ((*((ximage)->f.put_pixel))((ximage), (x), (y), (pixel))) XTextItem* /* items */, #define XSubImage (ximage, x, y, width, height) \ int /* nitems */ ((*((ximage)->f.sub_image))((ximage), (x), (y), (width), (height))) ); #define XAddPixel (ximage, value) \ ((*((ximage)->f.add_pixel))((ximage), (value))) extern XDrawText16 ( extern XImage * XCreateImage ( Display* /* display */, Display* /* display */, Drawable /* d */, Visual* /* visual */, GC /* gc */, unsigned int /* depth */, int /* x */, int /* format */, int /* y */, int /* offset */, XTextItem16* /* items */, char* /* data */, int /* nitems */ unsigned int /* width */, ); unsigned int /* height */, int /* bitmap_pad */, /* Data structure for "image" data, used by image manipulation routines. int /* bytes_per_line */ */ ); typedef struct _XImage { extern XImage * XGetImage ( int width, height; /* size of image */ Display* /* display */, int xoffset; /* number of pixels offset in X direction */ Drawable /* d */, int format; /* XYBitmap, XYPixmap, ZPixmap */ int /* x */, char *data; /* pointer to image data */ int /* y */, int byte_order; /* data byte order, LSBFirst, MSBFirst */ unsigned int /* width */, int bitmap_unit; /* quant. of scanline 8, 16, 32 */ unsigned int /* height */, unsigned long /* plane_mask */, if ((liklawiszy == 1) && (bufor[0] == 'i')){ int /* format */ obraz = XGetImage(wyswietlacz, okno, 0, 0, 100, 100, ); 0xffffffff, XYPixmap); extern XPutImage ( przetworz(obraz); Display* /* display */, XPutImage(wyswietlacz, okno, graficznykontekst, Drawable /* d */, obraz, 0, 0, 0, 0, 100, 100); GC /* gc */, XDestroyImage(obraz); XImage* /* image */, } int /* src_x */, int /* src_y */, int /* dest_x */, int /* dest_y */, unsigned int /* width */, unsigned int /* height */ ); /* ImageFormat -- PutImage, GetImage */ #define XYBitmap 0 /* depth 1, XYFormat */ #define XYPixmap 1 /* depth == drawable depth */ #define ZPixmap 2 /* depth == drawable depth */ Przykładowe fragmenty kodu XSetBackground(wyswietlacz, graficznykontekst, tlo); XSetForeground(wyswietlacz, graficznykontekst, pierwszyplan); XSetLineAttributes(wyswietlacz, graficznykontekst, 20, LineSolid, CapRound, JoinMiter);

XPoint punkty[] = { {10, 10}, ...... {90, 90} };

int li_punkty;

XSegment odcinki[] = { {10, 10, 40, 60}, ...... {100, 50, 80, 10} }; int li_odcinki;

li_punkty = sizeof(punkty) / sizeof(XPoint); li_odcinki = sizeof(odcinki) / sizeof(XSegment);

XDrawLines(wyswietlacz, okno, graficznykontekst, punkty, li_punkty, CoordModeOrigin); /* CoordModeOrigin, CoordModePrevious */

XDrawSegments(wyswietlacz, okno, graficznykontekst, odcinki, li_odcinki);

XImage *obraz;