Commit 56f29951 authored by Daniel Vogel's avatar Daniel Vogel

added events code

parent 4a606e66
/*
CS 349 Code Examples: X Windows and XLib
animation.cpp Ball bouncing in window (minimal version)
- - - - - - - - - - - - - - - - - - - - - -
See associated makefile for compiling instructions
*/
#include <cstdlib>
#include <iostream>
#include <unistd.h>
#include <sys/time.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
// get microseconds
unsigned long now() {
timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000000 + tv.tv_usec;
}
using namespace std;
Display* display;
Window window;
// frames per second to run animation loop
int FPS = 120;
int main( int argc, char *argv[] ) {
display = XOpenDisplay("");
if (display == NULL) exit (-1);
int screennum = DefaultScreen(display);
long background = WhitePixel(display, screennum);
long foreground = BlackPixel(display, screennum);
window = XCreateSimpleWindow(display, DefaultRootWindow(display),
10, 10, 300, 200, 2, foreground, background);
XSelectInput(display, window,
ButtonPressMask | KeyPressMask); // select events
XMapRaised(display, window);
XFlush(display);
XEvent event; // save the event here
// ball postition, size, and velocity
XPoint ballPos;
ballPos.x = 50;
ballPos.y = 50;
int ballSize = 50;
XPoint ballDir;
ballDir.x = 3;
ballDir.y = 3;
// create gc for drawing
GC gc = XCreateGC(display, window, 0, 0);
// time of last window paint
unsigned long lastRepaint = 0;
XWindowAttributes w;
XGetWindowAttributes(display, window, &w);
// event loop
while ( true ) {
// TRY THIS
// comment out this conditional to see what happens when
// events block (run the program and keep pressing the mouse)
if (XPending(display) > 0) {
XNextEvent( display, &event );
switch ( event.type ) {
// mouse button press
case ButtonPress:
cout << "CLICK" << endl;
break;
case KeyPress: // any keypress
KeySym key;
char text[10];
int i = XLookupString( (XKeyEvent*)&event, text, 10, &key, 0 );
if ( i == 1 && text[0] == 'q' ) {
XCloseDisplay(display);
exit(0);
}
break;
}
}
unsigned long end = now();
if (end - lastRepaint > 1000000 / FPS) {
// clear background
XClearWindow(display, window);
// draw ball from centre
XFillArc(display, window, gc,
ballPos.x - ballSize/2,
ballPos.y - ballSize/2,
ballSize, ballSize,
0, 360*64);
// update ball position
ballPos.x += ballDir.x;
ballPos.y += ballDir.y;
// bounce ball
if (ballPos.x + ballSize/2 > w.width ||
ballPos.x - ballSize/2 < 0)
ballDir.x = -ballDir.x;
if (ballPos.y + ballSize/2 > w.height ||
ballPos.y - ballSize/2 < 0)
ballDir.y = -ballDir.y;
XFlush( display );
lastRepaint = now(); // remember when the paint happened
}
// IMPORTANT: sleep for a bit to let other processes work
if (XPending(display) == 0) {
usleep(1000000 / FPS - (end - lastRepaint));
}
}
XCloseDisplay(display);
}
/*
CS 349 Code Examples: X Windows and XLib
doublebuffer.cpp How to do double buffering (minimal version)
Note, it's pretty hard to see any difference.
- - - - - - - - - - - - - - - - - - - - - -
See associated makefile for compiling instructions
*/
#include <cstdlib>
#include <iostream>
#include <unistd.h>
#include <sys/time.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
// get microseconds
unsigned long now() {
timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000000 + tv.tv_usec;
}
using namespace std;
Display* display;
Window window;
// frames per second to run animation loop
int FPS = 60;
int main( int argc, char *argv[] ) {
display = XOpenDisplay("");
if (display == NULL) exit (-1);
int screennum = DefaultScreen(display);
long background = WhitePixel(display, screennum);
long foreground = BlackPixel(display, screennum);
window = XCreateSimpleWindow(display, DefaultRootWindow(display),
10, 10, 300, 200, 2, foreground, background);
XSelectInput(display, window,
ButtonPressMask | KeyPressMask); // select events
XMapRaised(display, window);
XFlush(display);
XEvent event; // save the event here
// ball postition, size, and velocity
XPoint ballPos;
ballPos.x = 50;
ballPos.y = 50;
int ballSize = 50;
XPoint ballDir;
ballDir.x = 3;
ballDir.y = 3;
// create gc for drawing
GC gc = XCreateGC(display, window, 0, 0);
// time of last window paint
unsigned long lastRepaint = 0;
XWindowAttributes w;
XGetWindowAttributes(display, window, &w);
// DOUBLE BUFFER
// create bimap (pximap) to us a other buffer
int depth = DefaultDepth(display, DefaultScreen(display));
Pixmap buffer = XCreatePixmap(display, window, w.width, w.height, depth);
bool useBuffer = true;
// event loop
while ( true ) {
// TRY THIS
// comment out this conditional to see what happens when
// events block (run the program and keep pressing the mouse)
if (XPending(display) > 0) {
XNextEvent( display, &event );
switch ( event.type ) {
// mouse button press
case ButtonPress:
useBuffer = !useBuffer;
cout << "double buffer " << useBuffer << endl;
break;
case KeyPress: // any keypress
KeySym key;
char text[10];
int i = XLookupString( (XKeyEvent*)&event, text, 10, &key, 0 );
if ( i == 1 && text[0] == 'q' ) {
XCloseDisplay(display);
exit(0);
}
break;
}
}
unsigned long end = now();
if (end - lastRepaint > 1000000 / FPS) {
Pixmap pixmap;
if (useBuffer) {
pixmap = buffer;
// draw into the buffer
// note that a window and a pixmap are “drawables”
XSetForeground(display, gc, WhitePixel(display, DefaultScreen(display)));
XFillRectangle(display, pixmap, gc,
0, 0, w.width, w.height);
} else {
pixmap = window;
// clear background
XClearWindow(display, pixmap);
}
// draw ball from centre
XSetForeground(display, gc, BlackPixel(display, DefaultScreen(display)));
XFillArc(display, pixmap, gc,
ballPos.x - ballSize / 2,
ballPos.y - ballSize / 2,
ballSize, ballSize,
0, 360 * 64);
// update ball position
ballPos.x += ballDir.x;
ballPos.y += ballDir.y;
// bounce ball
if (ballPos.x + ballSize / 2 > w.width ||
ballPos.x - ballSize / 2 < 0)
ballDir.x = -ballDir.x;
if (ballPos.y + ballSize / 2 > w.height ||
ballPos.y - ballSize / 2 < 0)
ballDir.y = -ballDir.y;
// copy buffer to window
if (useBuffer) {
XCopyArea(display, pixmap, window, gc,
0, 0, w.width, w.height, // region of pixmap to copy
0, 0); // position to put top left corner of pixmap in window
}
XFlush( display );
lastRepaint = now(); // remember when the paint happened
}
// IMPORTANT: sleep for a bit to let other processes work
if (XPending(display) == 0) {
usleep(1000000 / FPS - (end - lastRepaint));
}
}
XCloseDisplay(display);
}
/*
CS 349 Code Examples: X Windows and XLib
eventloop Displays text at cursor location on mouse button press
- - - - - - - - - - - - - - - - - - - - - -
See associated makefile for compiling instructions
*/
#include <iostream>
#include <list>
#include <cstdlib>
#include <vector>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
using namespace std;
const int Border = 5;
const int BufferSize = 10;
struct XInfo {
Display* display;
Window window;
GC gc;
};
// An abstract class representing displayable things.
class Displayable {
public:
virtual void paint(XInfo& xinfo) = 0;
};
// A text displayable
class Text : public Displayable {
public:
virtual void paint(XInfo& xinfo) {
XDrawImageString( xinfo.display, xinfo.window, xinfo.gc,
this->x, this->y, this->s.c_str(), this->s.length() );
}
Text(int x, int y, string s): x(x), y(y), s(s) {}
private:
int x;
int y;
string s; // string to show
};
// A displayable polyline
class Polyline : public Displayable {
public:
virtual void paint(XInfo& xinfo) {
// note the trick to pass a stl vector as an C array
XDrawLines(xinfo.display, xinfo.window, xinfo.gc,
&points[0], points.size(), // vector of points
CoordModeOrigin ); // use absolute coordinates
}
Polyline(int x, int y) {
add_point(x, y);
}
// add another point to the line
void add_point(int x, int y) {
XPoint p;
p.x = x;
p.y = y;
points.push_back(p);
}
private:
// need to use a vector to dynamically add points
vector < XPoint > points; // XPoint is a built in struct
};
// Function to put out a message on error exits.
void error( string str ) {
cerr << str << endl;
exit(0);
}
// Function to repaint a display list
void repaint( list<Displayable*> dList, XInfo& xinfo) {
list<Displayable*>::const_iterator begin = dList.begin();
list<Displayable*>::const_iterator end = dList.end();
XClearWindow( xinfo.display, xinfo.window );
while ( begin != end ) {
Displayable* d = *begin;
d->paint(xinfo);
begin++;
}
XFlush( xinfo.display );
}
// The loop responding to events from the user.
void eventloop(XInfo& xinfo) {
XEvent event;
KeySym key;
char text[BufferSize];
list<Displayable*> dList;
Polyline* polyline = NULL;
while ( true ) {
XNextEvent( xinfo.display, &event );
switch ( event.type ) {
// Repaint the window on expose events.
case Expose:
cout << "Expose count " << event.xexpose.count << endl;
if ( event.xexpose.count == 0 ) {
repaint( dList, xinfo);
}
break;
// add item where mouse clicked
case ButtonPress:
// output to console
cout << "ButtonPress at " << event.xbutton.time << endl;
// add a new text object to the display list
dList.push_back(new Text(event.xbutton.x, event.xbutton.y, "CLICK"));
// start a new polyline to draw
polyline = new Polyline(event.xbutton.x, event.xbutton.y);
dList.push_back(polyline);
repaint( dList, xinfo );
break;
// add item where mouse moved
case MotionNotify:
// add a new text object to the display list
//dList.push_back(new Text(event.xmotion.x, event.xmotion.y, "C"));
// add the point to the drawing
if (polyline != NULL) {
polyline->add_point(event.xmotion.x, event.xmotion.y);
}
repaint( dList, xinfo );
break;
/*
* Exit when 'q' is typed.
* Arguments for XLookupString :
* event - the keyboard event
* text - buffer into which text will be written
* BufferSize - size of text buffer
* key - workstation independent key symbol
* 0 - pointer to a composeStatus structure
*/
case KeyPress:
int i = XLookupString( (XKeyEvent*)&event, text, BufferSize, &key, 0 );
cout << "KeySym " << key
<< " text='" << text << "'"
<< " at " << event.xkey.time
<< endl;
if ( i == 1 && text[0] == 'q' ) {
cout << "Terminated normally." << endl;
XCloseDisplay(xinfo.display);
return;
}
break;
}
}
}
// Create the window; initialize X.
void initX(int argc, char* argv[], XInfo& xinfo) {
xinfo.display = XOpenDisplay( "" );
if ( !xinfo.display ) {
error( "Can't open display." );
}
int screen = DefaultScreen( xinfo.display );
unsigned long background = WhitePixel( xinfo.display, screen );
unsigned long foreground = BlackPixel( xinfo.display, screen );
XSizeHints hints;
hints.x = 100;
hints.y = 100;
hints.width = 400;
hints.height = 300;
hints.flags = PPosition | PSize;
xinfo.window = XCreateSimpleWindow( xinfo.display, DefaultRootWindow( xinfo.display ),
hints.x, hints.y, hints.width, hints.height,
Border, foreground, background );
XSetStandardProperties( xinfo.display, xinfo.window, "eventloop", "eventloop", None,
argv, argc, &hints );
xinfo.gc = XCreateGC (xinfo.display, xinfo.window, 0, 0 );
XSetBackground( xinfo.display, xinfo.gc, background );
XSetForeground( xinfo.display, xinfo.gc, foreground );
// Tell the window manager what input events you want.
XSelectInput( xinfo.display, xinfo.window,
ButtonPressMask | KeyPressMask |
ExposureMask | ButtonMotionMask );
XMapRaised( xinfo.display, xinfo.window );
}
int main ( int argc, char* argv[] ) {
XInfo xinfo;
initX(argc, argv, xinfo);
eventloop(xinfo);
}
/*
CS 349 Code Examples: X Windows and XLib
eventloop.min.cpp Demos events by displaying mouse motion events
to console (minimal version)
- - - - - - - - - - - - - - - - - - - - - -
See associated makefile for compiling instructions
*/
#include <cstdlib>
#include <iostream>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
using namespace std;
Display* display;
Window window;
int main( int argc, char *argv[] ) {
display = XOpenDisplay("");
if (display == NULL) exit (-1);
int screennum = DefaultScreen(display);
long background = WhitePixel(display, screennum);
long foreground = BlackPixel(display, screennum);
window = XCreateSimpleWindow(display, DefaultRootWindow(display),
10, 10, 300, 200, 2, foreground, background);
XSelectInput(display, window,
PointerMotionMask | KeyPressMask); // select events
XMapRaised(display, window);
XFlush(display);
XEvent event; // save the event here
while ( true ) { // event loop until 'exit'
XNextEvent( display, &event ); // wait for next event
switch ( event.type ) {
case MotionNotify: // mouse movement
cout << event.xmotion.x << ","
<< event.xmotion.y << endl;
break;
case KeyPress: // any keypress
exit(0);
break;
}
}
XCloseDisplay(display);
}
/*
CS 349 Code Examples: X Windows and XLib
xballeyes.cpp Demos complex drawing, events, and animation.
Note the even loop is blocking!
- - - - - - - - - - - - - - - - - - - - - -
See associated makefile for compiling instructions
*/
#include <iostream>
#include <list>
#include <cstdlib>
#include <sys/time.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
using namespace std;
const int Border = 10;
const int BufferSize = 10;
const int FPS = 30;
// save even more more information about the window ...
struct XInfo {
Display *display;
int screen;
Window window;
// three GCs!
GC gc[3];
// size of window
int width;
int height;
};
void error( string str ) {
cerr << str << endl;
exit(0);
}
// An abstract class representing displayable things.
class Displayable {
public:
virtual void paint(XInfo &xinfo) = 0;
};
class Eye : public Displayable {
public:
virtual void paint(XInfo &xinfo) {
XFillArc(xinfo.display, xinfo.window, xinfo.gc[1], x, y, width, height, 0, 360*64);
double cx = x + width/2;
double cy = y + height/2;
double alpha;
if (look_x > cx ) alpha = atan((look_y - cy) / (look_x - cx) );
else alpha = M_PI - atan((look_y - cy) / (cx - look_x) );
XFillArc(xinfo.display, xinfo.window, xinfo.gc[0],
cx + cos(alpha)*width/4 - width/8,
cy + sin(alpha)*height/4 - height/8,
width/4, height/4,
0,
360*64);
}
void lookat(int x, int y) {
look_x = x;
look_y = y;
}
// constructor
Eye(int x, int y, int width, int height):x(x), y(y), width(width), height(height) {
look_x = x+width/2;
look_y = y+height/2;
}
private:
int x;
int y;
int width;
int height;
int look_x;
int look_y;
};
class Ball : public Displayable {
public:
virtual void paint(XInfo &xinfo) {
XFillArc(xinfo.display, xinfo.window, xinfo.gc[1], x, y, diameter, diameter, 0, 360*64);
}
void move(XInfo &xinfo) {
x = x + direction;
if (random() % 100 == 0 || x < 0 || x > xinfo.width - diameter) {
direction = -direction;
}
}
int getX() {
return x;
}
int getY() {
return y;
}
Ball(int x, int y, int diameter): x(x), y(y), diameter(diameter) {
direction = 4;
}
private: