# HG changeset patch # User Eris Caffee # Date 1334997626 18000 # Node ID c5c33bf5f1fba72d2d0640ed96971411e980f602 # Parent 713e3c5db1e1d54f783e30306368b55777c49532 Basic demo framework seems good diff -r 713e3c5db1e1 -r c5c33bf5f1fb include/App.h --- a/include/App.h Wed Apr 18 00:53:10 2012 -0500 +++ b/include/App.h Sat Apr 21 03:40:26 2012 -0500 @@ -90,4 +90,5 @@ long event_mask; Atom wm_delete_window; // Need this in contructor and run(). + std::string button_state_string(unsigned int state) const; }; diff -r 713e3c5db1e1 -r c5c33bf5f1fb src/App.cpp --- a/src/App.cpp Wed Apr 18 00:53:10 2012 -0500 +++ b/src/App.cpp Sat Apr 21 03:40:26 2012 -0500 @@ -87,7 +87,13 @@ // Select the event types we want to receive. //Other interesting events include KeyReleaseMask and ButtonReleaseMask - event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask ; + event_mask = + ExposureMask | StructureNotifyMask | + KeyPressMask | KeyReleaseMask | + FocusChangeMask | + PointerMotionMask | + EnterWindowMask | LeaveWindowMask | + ButtonPressMask | ButtonReleaseMask ; XSelectInput(dpy, wd->win, event_mask); @@ -200,6 +206,9 @@ { switch (e.type) { + + //////////////////////// + // General window events case Expose: // We'll only redraw the entire window at a time, so unless this is // the last contiguous expose, don't draw the window. @@ -211,7 +220,46 @@ if ((Atom)e.xclient.data.l[0] == wm_delete_window) done = 1; break; + + /////////////////////// + // Mouse events + case MotionNotify: + std::cout << "Mouse at (" << e.xmotion.x << "," << e.xmotion.y << ")" << std::endl; + break; case ButtonPress: + std::cout << "You pressed button " << e.xbutton.button << + " at (" << e.xbutton.x << "," << e.xbutton.y << ")" << + " state " << button_state_string(e.xbutton.state ) << std::endl; + break; + case ButtonRelease: + std::cout << "You released button " << e.xbutton.button << + " at (" << e.xbutton.x << "," << e.xbutton.y << ")" << + " state " << button_state_string(e.xbutton.state ) << std::endl; + break; + case EnterNotify: + std::cout << "Mouse has entered the window" << + " at (" << e.xbutton.x << "," << e.xbutton.y << ")" << + " state " << button_state_string(e.xbutton.state ) << std::endl; + break; + case LeaveNotify: + std::cout << "Mouse has left the window" << + " at (" << e.xbutton.x << "," << e.xbutton.y << ")" << + " state " << button_state_string(e.xbutton.state ) << std::endl; + break; + + ////////////////// + // Keyboard Events + case FocusIn: + // Interesting note: When we regain focus due to a mouse click in the window, + // we first get a LeaveNotify, then the FocusIn, then an EnterNotify, and then + // the ButtonPress and ButtonRelease. So in a real app we might want to have + // the FocusIn handler read ahead and handle (discard) the next ButtonPress, + // and ButtonRelease so that the click does not have a real effect on the application. + std::cout << "Got keyboard focus" << std::endl; + break; + case FocusOut: + std::cout << "Lost keyboard focus" << std::endl; + break; case KeyPress: // Doing the lookup like this, using XLookupString, means I get the modified // character back. Thus type shift+a gives me XK_A instead of XK_a @@ -232,6 +280,13 @@ std::cout << "You typed " << key_buffer << std::endl; break; } + case MappingNotify: + // While it is uncommon for the user to change the keyboard mapping while + // a program is running, handling this case is so trivial that there is + // simply no excuse to leave it out. + XRefreshKeyboardMapping((XMappingEvent *)&e); + break; + default: break; } @@ -243,6 +298,26 @@ } //////////////////////////////////////////////////////////////////////////////// +std::string App::button_state_string(unsigned int state) const + { + std::string str = ""; + if (state & Button1Mask) { str.append("Button1 "); } + if (state & Button2Mask) { str.append("Button2 "); } + if (state & Button3Mask) { str.append("Button3 "); } + if (state & Button4Mask) { str.append("Button4 "); } + if (state & Button5Mask) { str.append("Button5 "); } + if (state & ShiftMask) { str.append("Shift "); } + if (state & LockMask) { str.append("Lock "); } + if (state & ControlMask) { str.append("Control "); } + if (state & Mod1Mask) { str.append("Mod1 "); } + if (state & Mod2Mask) { str.append("Mod2 "); } + if (state & Mod3Mask) { str.append("Mod3 "); } + if (state & Mod4Mask) { str.append("Mod4 "); } + if (state & Mod5Mask) { str.append("Mod5 "); } + return str; + } + +//////////////////////////////////////////////////////////////////////////////// // App::BitMap //////////////////////////////////////////////////////////////////////////////// App::BitMap::BitMap(const std::string & file)