X Window System programming

0

Używam następujących bibliotek: Xlib, Xdbe. Korzystam też z pthreads, ale tylko jeden wątek ma dostęp do wywołań Xlib.
Napotkałem na następujące problemy:
pętla zdarzeń - jak poprawnie zaimplementować pętlę zdarzeń? Pętla powinna przyjmować zdarzenia od serwera X oraz przerysowywać okno (lub okna) gdy dostanie taką informację od innego wątku. Ok, mogę korzystać z wywołania XCheckWindowEvent, dla konkretnego okna, a potem sprawdzić czy potrzeba przerysować okno, ale co dalej? usleep? Dajcie mi info o tym jak powinna wyglądać pętla zdarzeń.
rysowanie - rysuję na back-buforze potem swap. Program rysował około 3200 linii, co sprawiło, że Xorg zajmował cały rdzeń procesora, i spadł FPS. Nie sprawdziłem jeszcze działania XDrawLines, które rysuje kilka linni przy jednym wywołaniu. Pytanie: jak rysować, gdzie rysować?

Zatem, jest duża liczba tekstów, jak korzystać z Xlib, ale nie znalazłem jeszcze żadnego o tym jak utworzyć dobre GUI w Xlib.

Proszę o jakiekolwiek informacje.

0

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <string.h>

#define TRUE 1
#define FALSE 0
 
#define MAXF 400 // maks. ilość przechowywanych w tablicy figur
#define MAXK 5 // ilość kolorów w tablicy
#define PWIDTH 100 // długość prostokąta
#define PHEIGHT 60 // wysokość prostokąta
#define KWIDTH 80 // średnica koła
 
 
typedef struct { // struktura figura; x,y-współrzędne środka figury, typ - 1 oznacza prostokąt, 2 koło, kolor - numer koloru z tablicy
    int x, y, typ, kolor;
} figura;
 
int main(int argc, char *argv[])
{
  char            icon_name[] = "Grafika";
  char            title[]     = "Grafika komputerowa";
  Display*        display;    //gdzie bedziemy wysylac dane (do jakiego X servera)
  Window          window;     //nasze okno, gdzie bedziemy dokonywac roznych operacji
  GC              gc;         //tu znajduja sie informacje o parametrach graficznych
  XEvent          event;      //gdzie bedziemy zapisywac pojawiajace sie zdarzenia
  KeySym          key;        //informacja o stanie klawiatury
  XSizeHints      info;       //informacje typu rozmiar i polozenie okna
  int             screen_no;
  unsigned long   foreground;
  unsigned long   background;
  char            buffer[8];  //gdzie bedziemy zapamietywac znaki z klawiatury
  int             hm_keys;    //licznik klawiszy
 
  int             to_end;
  XPoint          current_point;
 
  Colormap        colormap;
  int             red, green, blue, yellow;
 
  figura          figbuf[MAXF]; // tablica z figurami
 
  int fi=0,fim=0,i=0,idf=-1; // zmienne pomocnicze
  int kolor[MAXK]; // tablica kolorów
  double odleglosc=0; // zmienna pomocnicza do obliczania odległości
 
  display    = XOpenDisplay("");                //otworz polaczenie z X serverem pobierz dane od zmiennej srodowiskowej DISPLAY ("")
  screen_no  = DefaultScreen(display);          //pobierz domyslny ekran dla tego wyswietlacza (0)
  background = WhitePixel(display, screen_no);  //niech tlo bedzie biale
  foreground = BlackPixel(display, screen_no);  //niech ekran bedzie czarny
 
  colormap = DefaultColormap(display,screen_no);
 
  int AllocNamedColor(char *name)     //funkcja przydzielania kolorow
  {
    XColor col;
    XParseColor(display,colormap,name,&col);
    XAllocColor(display,colormap,&col);
    return col.pixel;
  }
 
  red=AllocNamedColor("red");
  green=AllocNamedColor("green");
  blue=AllocNamedColor("blue");
  yellow=AllocNamedColor("yellow");
 
// kolory w tablicy
kolor[0]=AllocNamedColor("black");
kolor[1]=red;
kolor[2]=green;
kolor[3]=blue;
kolor[4]=yellow;
 
  //okresl rozmiar i polozenie okna
  info.x = 100;
  info.y = 150;
  info.width = 600;
  info.height = 300;
  info.flags = PPosition | PSize;
 
  //majac wyswietlacz, stworz okno - domyslny uchwyt okna
  window = XCreateSimpleWindow(display, DefaultRootWindow(display),
                               info.x, info.y, info.width, info.height,
                               7/* grubosc ramki */, foreground, background);
  XSetStandardProperties(display, window, title, icon_name, None,
                         argv, argc, &info);
  //utworz kontekst graficzny do zarzadzania parametrami graficznymi (0,0) domyslne wartosci
  gc = XCreateGC(display, window, 0, 0);
 
  XSetBackground(display, gc, background);
  XSetForeground(display, gc, foreground);
 
/* okresl zdarzenia jakie nas interesuja tj. nacisniecie
     klawisza (aby wyjsc z programu, oraz zdarzenie
     odswiezania okna np. gdy jakies inne window, ktore
     przykrywalo nasze okno zostalo zamkniete lub przesuniete,
     nacisniecie klawisza, zwolnienie oraz ruch myszy*/
  XSelectInput(display, window, (KeyPressMask | ExposureMask | ButtonPressMask|
                                 ButtonReleaseMask | Button1MotionMask));
  XMapRaised(display, window);  //wyswietl nasze okno na samym wierzchu wszystkich okien
 
  to_end = FALSE;
 
 
 /* petla najpierw sprawdza, czy warunek jest spelniony
     i jesli tak, to nastepuje przetwarzanie petli
     a jesli nie, to wyjscie z petli, bez jej przetwarzania */
  while (to_end == FALSE)
  {
    XNextEvent(display, &event);  // czekaj na zdarzenia okreslone wczesniej przez funkcje XSelectInput
 
    switch(event.type)
    {
      case Expose:
        if (event.xexpose.count == 0)
        {
        //tu powinna byc przerysowana zawartosc okna
       
        for (i=0;i<=fim;i++) { // przechodzimy przez tablicę figur
       
            XSetForeground(display, gc, kolor[figbuf[i].kolor]); // ustawiamy kolor jakim mamy narysować figurę
 
            if (figbuf[i].typ==1) {
                XFillRectangle(display,window,gc,figbuf[i].x-(PWIDTH/2),figbuf[i].y-(PHEIGHT/2),PWIDTH,PHEIGHT); // rysujemy prostokąt
            } else if (figbuf[i].typ==2) {
                XFillArc(display,window,gc,figbuf[i].x-(KWIDTH/2),figbuf[i].y-(KWIDTH/2),KWIDTH,KWIDTH,0,360*64); // rysujemy koło
            }
           
        }
           
        }
        break;
 
      case MappingNotify:
        XRefreshKeyboardMapping(&event.xmapping); // zmiana ukladu klawiatury - w celu zabezpieczenia sie przed taka zmiana trzeba to wykonac
        break;
 
      case ButtonPress:
        if (event.xbutton.button == Button1 || event.xbutton.button == Button3)  // sprawdzenie czy wciscnieto lewy lub prawy przycisk
        {
 
          //odczytanie polozenia kursora
          current_point.x = event.xbutton.x;
          current_point.y = event.xbutton.y;
 
            for (i=0;i<=fim;i++) { // przechodzimy w pętli przez tablicę figur w celu sprawdzenia czy kliknięto na figurze
                odleglosc = ((current_point.x-figbuf[i].x)*(current_point.x-figbuf[i].x))+((current_point.y-figbuf[i].y)*(current_point.y-figbuf[i].y));//obliczamy odległość punktu kliknięcia od środka figury
 
                    if (current_point.x >= figbuf[i].x-(PWIDTH/2) && current_point.x <= figbuf[i].x+(PWIDTH/2) && current_point.y >= figbuf[i].y-(PHEIGHT/2) && current_point.y <= figbuf[i].y+(PHEIGHT/2) && figbuf[i].typ==1) idf=i;
                    else if (odleglosc<=(KWIDTH/2)*(KWIDTH/2) && figbuf[i].typ==2) idf=i; // przypisanie do idf id figury z tablicy jeśli kliknięto na nią
 
            }
               
            if (idf>=0) { // jeśli kliknięto figurę zmieniamy kolor
                figbuf[idf].kolor++;
                if (figbuf[idf].kolor>=MAXK) figbuf[idf].kolor=0; // jeśli nie ma już koloru w tablicy przypisujemy pierwszy kolor
            } else { // jesli nie robimy nową
 
                      if (fi>=MAXF) fi=0; // jesli id wychodzi poza zakres nadpisujemy 1 figurę
                      if (fim>MAXF) fim=MAXF; // ilość elementów w tablicy
               
                      figbuf[fi].x=current_point.x; // x srodka
                      figbuf[fi].y=current_point.y; // y srodka
                      figbuf[fi].typ=(event.xbutton.button==Button1?1:2); // jesli kliknieto lewy typ 1 (prostokat) figury jesli nie typ 2 (kolo)
                      figbuf[fi].kolor=0; // kolor czarny
 
                      fim++;fi++;
            }
 
            idf=-1; // czyszczenie idf
 
          // wymuszenie odswiezenia okna
          event.type = Expose;          
          event.xexpose.count = 0;
          XSendEvent(display, window, 0, ExposureMask, &event);
        }
        break;
 
      case KeyPress:
        hm_keys = XLookupString(&event.xkey, buffer, 8, &key, 0);
        if (hm_keys == 1)
        {
          if (buffer[0] == 'q') to_end = TRUE;        // koniec programu
         
        }
 
      default:
        break;
    }
  }
 
  XFreeGC(display, gc);
  XDestroyWindow(display, window);
  XCloseDisplay(display);
 
  return 0;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1