4 #include <X11/extensions/XInput2.h>
18 virtual void render (Display*, Window&, GC&) = 0;
21 class TextRenderable : public Renderable {
24 int color; // text color
25 std::string text; // what to render
26 //bool centered; // render centered // TODO
28 TextRenderable (int posx, int posy, int textcolor, const char * message)
29 : x(posx), y(posy), color(textcolor), text(message) {}
31 virtual void render (Display * dpy, Window & w, GC & gc) {
32 XSetForeground(dpy, gc, color);
33 XDrawString(dpy, w, gc, x, y, text.c_str(), text.length());
41 TextRenderable * textField;
46 Player () : name(), isReady(false), indexToType(0), score(0) {}
50 void associateTextField (TextRenderable * t) {
53 void nameInput (const char * input) {
56 if (strlen(input) == 1) {
57 textField->text.append(input);
58 } else if (strcmp (input, "Return") == 0) {
59 name = textField->text;
61 textField->text.append(" READY");
62 } else if (strcmp (input, "BackSpace") == 0 && name.length() > 0) {
63 textField->text.erase (textField->text.length()-1);
66 // returns if player has just finished the word
67 bool input (const char * input, const std::string & currentWord) {
68 if (strlen(input) == 1 && currentWord[indexToType] == input[0] && !isReady) {
69 assert (textField != NULL);
70 assert (indexToType >= 0);
71 textField->text.push_back(input[0]);
73 if (currentWord.length() == (unsigned int)indexToType) { // done
75 textField->text.erase();
83 textField->text.erase();
86 void addScore (int toAdd) {
96 const char * getName () {
101 void clearScreen (Display *d, Window& window, GC& gc, int color) {
102 XSetForeground (d, gc, color);
103 unsigned int width,height; // TODO: nicht jedes mal die query machen
104 unsigned int dummyu; int dummyi; Window dummyw;
105 XGetGeometry(d, window, &dummyw, &dummyi, &dummyi, &width, &height, &dummyu, &dummyu);
106 XFillRectangle (d, window, gc, 0, 0, width, height);
109 void render (Display *d, Window& window, GC& gc, int bgcolor, std::vector < Renderable* > & toRender) {
110 clearScreen (d, window, gc, bgcolor);
111 for (size_t i=0; i<toRender.size(); i++) {
112 toRender[i]->render(d, window, gc);
117 int getColorExact (Display *d, int r, int g, int b) {
118 int screen = DefaultScreen(d);
119 Colormap cmap = DefaultColormap(d,screen);
121 if (r > 65535) r = 65535;
122 if (g > 65535) g = 65535;
123 if (b > 65535) b = 65535;
126 c.red = r; c.green = g; c.blue = b;
128 if (XAllocColor(d, cmap, &c)) {
129 if (c.red != r || c.green != g || c.blue != b) {
130 fprintf (stderr, "(%d,%d,%d) -> (%d,%d,%d)\n", r, g, b, c.red, c.green, c.blue);
134 fprintf (stderr, "Warning: couldn't allocate color %d %d %d\n", r, g, b);
135 return BlackPixel(d,screen);
139 int getColor (Display *d, int r, int g, int b) {
141 return getColorExact (d, r*257, g*257, b*257);
144 std::string getNextWord (bool * isWord_return) {
146 std::getline (std::cin, ret);
147 *isWord_return = !std::cin.eof();
151 int main (int argc, char** argv) {
152 /* Connect to the X server */
153 Display *dpy = XOpenDisplay(NULL);
155 fprintf (stderr, "XOpenDisplay returned no display to display what is to display. Aborting.\n");
159 /* XInput Extension available? */
160 int opcode, event, error;
161 if (!XQueryExtension(dpy, "XInputExtension", &opcode, &event, &error)) {
162 printf("X Input extension not available.\n");
166 /* Which version of XI2? We support 2.0 */
167 int major = 2, minor = 0;
168 if (XIQueryVersion(dpy, &major, &minor) == BadRequest) {
169 printf("XI2 not available. Server supports %d.%d\n", major, minor);
173 printf ("system is sane.\n");
176 int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
177 int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));
181 TextRenderable playerTextFields [] = {
182 TextRenderable(0, 200, getColor (dpy, 255, 220, 32), ""),
183 TextRenderable(0, 300, getColor (dpy, 32, 128, 255), ""),
184 TextRenderable(0, 400, getColor (dpy, 64, 255, 0), ""),
185 TextRenderable(0, 500, getColor (dpy, 255, 0, 64), "")
189 Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 800, 600, 0, blackColor, blackColor);
191 // which events we want?
192 XSelectInput(dpy, w, StructureNotifyMask);
194 // put window on the screen
197 // create graphics context
198 GC gc = XCreateGC(dpy, w, 0, NULL);
200 // wait for MapNotify
204 if (e.type == MapNotify)
208 // Now let's listen to keypress events
209 XIEventMask eventmask;
210 unsigned char mask [1] = { 0 }; // will change
211 eventmask.deviceid = XIAllMasterDevices;
212 eventmask.mask_len = sizeof (mask); // in bytes, for whatever reason...
213 eventmask.mask = mask;
214 XISetMask(mask, XI_KeyPress);
215 XISelectEvents (dpy, w, &eventmask, 1);
216 XSelectInput (dpy, w, ExposureMask);
218 // setup player data structures
219 std::map < int , Player* > kbd2player;
220 std::vector< Player* > players;
222 // setup rendering stuff
223 std::vector< Renderable* > toRender;
224 for (int i = 0; i < maxplayers; i++)
225 toRender.push_back (playerTextFields+i);
226 TextRenderable mainTextField (50, 50, whiteColor, "Please type your name and then hit Return.");
227 toRender.push_back (&mainTextField);
229 bool allReady = false;
231 render(dpy, w, gc, blackColor, toRender);
233 XNextEvent(dpy, &ev);
234 if (ev.xcookie.type == GenericEvent && ev.xcookie.extension == opcode
235 && ev.xcookie.evtype == XI_KeyPress && XGetEventData(dpy, &ev.xcookie)) {
236 XIDeviceEvent *d_ev = (XIDeviceEvent*) ev.xcookie.data;
237 KeyCode keycode = d_ev->detail;
238 int kbdid = d_ev->deviceid;
239 if (!(d_ev->flags & XIKeyRepeat)) {
240 int keysyms_per_keycode;
241 //KeySym *keysym = XGetKeyboardMapping (dpy, keycode, 1, &keysyms_per_keycode);
242 KeySym keysym = XGetKeyboardMapping (dpy, keycode, 1, &keysyms_per_keycode)[0];
243 Player * eventPlayer;
244 if (kbd2player.count(kbdid) == 0) { // add player
245 if (nplayers == maxplayers) {
246 fprintf (stderr, "zu viele Spieler, TODO: gescheites error handling. Bye ;-)\n");
249 eventPlayer = new Player ();
250 eventPlayer->associateTextField (playerTextFields+nplayers);
252 players.push_back(eventPlayer);
253 kbd2player[kbdid] = eventPlayer;
254 } else { // player already there
255 eventPlayer = kbd2player[kbdid];
257 //debug out: mainTextField.text.append (XKeysymToString (keysym[0]));
258 eventPlayer->nameInput (XKeysymToString (keysym));
261 XFreeEventData(dpy, &ev.xcookie);
262 if (keycode == 9) {// Escape Key
263 printf ("you escaped successfully.\n");
266 } else if (ev.type == Expose) {
267 printf ("exposeevent\n");
269 printf ("other event\n");
272 if (!players.empty()) {
274 for (size_t i=0; i<players.size() && allReady; i++) {
275 allReady &= players[i]->getReady();
280 for (size_t i=0; i<players.size() && allReady; i++) {
281 players[i]->clearText();
282 players[i]->unsetReady();
283 } // readyflag will now be used for if they are already done with a word
285 int notreadyplayers = 0;
289 assert (notreadyplayers >= 0);
290 if (notreadyplayers == 0 || (notreadyplayers==1 && players.size()>1)) {
292 theWord = getNextWord(&gotWord);
295 mainTextField.text = theWord;
296 notreadyplayers = players.size();
297 for (size_t i=0; i<players.size() && allReady; i++) {
298 players[i]->unsetReady();
299 players[i]->clearText();
300 printf ("cleared text\n");
303 render(dpy, w, gc, blackColor, toRender);
305 XNextEvent(dpy, &ev);
306 if (ev.xcookie.type == GenericEvent && ev.xcookie.extension == opcode
307 && ev.xcookie.evtype == XI_KeyPress && XGetEventData(dpy, &ev.xcookie)) {
308 XIDeviceEvent *d_ev = (XIDeviceEvent*) ev.xcookie.data;
309 KeyCode keycode = d_ev->detail;
310 int kbdid = d_ev->deviceid;
311 if (!(d_ev->flags & XIKeyRepeat)) {
312 printf ("got key event\n");
313 int keysyms_per_keycode;
314 //KeySym *keysym = XGetKeyboardMapping (dpy, keycode, 1, &keysyms_per_keycode);
315 KeySym keysym = XGetKeyboardMapping (dpy, keycode, 1, &keysyms_per_keycode)[0];
316 Player * eventPlayer;
317 if (kbd2player.count(kbdid) == 0) { // add player
318 printf ("you can't join in a match\n");
320 /*if (nplayers == maxplayers) {
321 fprintf (stderr, "zu viele Spieler, TODO: gescheites error handling. Bye ;-)\n");
324 eventPlayer = new Player ();
325 eventPlayer->associateTextField (playerTextFields+nplayers);
327 players.push_back(eventPlayer);
328 kbd2player[srcid] = eventPlayer; */
329 } else { // player already there
330 eventPlayer = kbd2player[kbdid];
332 //debug out: mainTextField.text.append (XKeysymToString (keysym[0]));
333 bool pfinished = eventPlayer->input (XKeysymToString (keysym), theWord);
336 eventPlayer->addScore (notreadyplayers);
337 printf ("score of %d added\n", notreadyplayers);
341 XFreeEventData(dpy, &ev.xcookie);
342 if (keycode == 9) {// Escape Key
343 printf ("you escaped successfully.\n");
346 } else if (ev.type == Expose) {
347 printf ("exposeevent\n");
349 printf ("other event\n");