/* first include the standard headers that we're likely to need */ #include #include #include #include #include #include #include #include #include class threadDrawing { public: Display* d; Drawable w; Pixmap p; GC gc; pthread_t t; threadDrawing() : d( 0 ), w( 0 ), p( 0 ), gc( 0 ) { } ~threadDrawing() { deinit(); } void init( const char * dname ) { d = XOpenDisplay( dname ); int screen_num = XDefaultScreen(d); unsigned long bg = XBlackPixel(d, screen_num); unsigned long fg = XWhitePixel(d, screen_num); w = XCreateSimpleWindow(d, XDefaultRootWindow(d), 0, 0, 1, 1, 0, fg, bg ); p = XCreatePixmap( d, w, 50, 50, XDefaultDepth( d, XDefaultScreen( d ) ) ); gc = XCreateGC( d, w, 0, 0 ); XSetForeground( d, gc, fg ); XSetBackground( d, gc, bg ); } void deinit() { if ( gc ) { XFreeGC( d, gc ); gc = 0; } if ( p ) { XFreePixmap( d, p ); p = 0; } if ( w ) { XDestroyWindow( d, w ); w = 0; } if ( d ) { XCloseDisplay( d ); d = 0; } } static void* entry_point( void * pData) { threadDrawing* pThis = reinterpret_cast(pData); pThis->run(); return 0; } void start() { int rc = pthread_create( &t, 0, &entry_point, (void*)this ); std::cout << "Thread " << t << " created." << std::endl ; } void join() { void * s; pthread_join( t, &s ); std::cout << "Thread " << t << " joined." << std::endl ; } void run() { // p = XCreatePixmap( d, w, 50, 50, // XDefaultDepth( d, XDefaultScreen( d ) ) ); // GC gc = XCreateGC( d, w, 0, 0 ); XFillRectangle( d, p, gc, 0, 0, 50, 50 ); for (; true ; ) { XDrawLine( d, p, gc, 0, 0, 50, 50 ); XDrawLine( d, p, gc, 0, 50, 50, 0 ); } XFlush( d ); XSync( d, True ); } }; void createThreads( Display* d, Drawable w ) { const int tsize = 16; typedef std::vector threads_type; threads_type threads( tsize ); const char * dname = XDisplayString( d ); threads_type::iterator it = threads.begin(); threads_type::iterator itEnd = threads.end(); for ( ; it != itEnd; ++it ) { it->init( dname ); it->start(); } for ( it = threads.begin(); it != itEnd; ++it ) { it->join(); } } int error_handler( Display* d, XErrorEvent* err ) { puts( "error." ); } int io_error_handler( Display* d ) { puts( "io error." ); } int main(int argc, char ** argv) { int screen_num, width, height; unsigned long background, border; Window win; XEvent ev; Display *dpy; XSetErrorHandler( error_handler ); XSetIOErrorHandler( io_error_handler ); /* First connect to the display server, as specified in the DISPLAY environment variable. */ dpy = XOpenDisplay(NULL); if (!dpy) { fprintf(stderr, "unable to connect to display"); return 7; } /* these are macros that pull useful data out of the display object */ /* we use these bits of info enough to want them in their own variables */ screen_num = DefaultScreen(dpy); background = BlackPixel(dpy, screen_num); border = WhitePixel(dpy, screen_num); width = 400; /* start with a small window */ height = 400; win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), /* display, parent */ 0,0, /* x, y: the window manager will place the window elsewhere */ width, height, /* width, height */ 2, border, /* border width & colour, unless you have a window manager */ background); /* background colour */ /* tell the display server what kind of events we would like to see */ XSelectInput(dpy, win, ButtonPressMask|StructureNotifyMask ); /* okay, put the window on the screen, please */ XMapWindow(dpy, win); // // // createThreads( dpy, win ); /* as each event that we asked about occurs, we respond. In this * case we note if the window's shape changed, and exit if a button * is pressed inside the window */ while(1) { XNextEvent(dpy, &ev); switch(ev.type) { case ConfigureNotify: if (width != ev.xconfigure.width || height != ev.xconfigure.height) { width = ev.xconfigure.width; height = ev.xconfigure.height; printf("Size changed to: %d by %d\n", width, height); } break; case ButtonPress: XCloseDisplay(dpy); return 0; } } }