diff --git a/x/2-4-EventDispatch/makefile b/x/2-4-EventDispatch/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..39cdb46c8a09a6296a1195b0f16836fcece33e32
--- /dev/null
+++ b/x/2-4-EventDispatch/makefile
@@ -0,0 +1,19 @@
+# super simple makefile
+# call it using 'make NAME=name_of_code_file_without_extension'
+# (assumes a .cpp extension)
+NAME = "multiwindow"
+
+# Add $(MAC_OPT) to the compile line for macOS 
+# (should be ignored by Linux, set to nothing if causing problems)
+MAC_OPT = -I/opt/X11/include
+
+all:
+	@echo "Compiling..."
+	g++ -o $(NAME) $(NAME).cpp -L/opt/X11/lib -lX11 -lstdc++ $(MAC_OPT)
+
+run: all
+	@echo "Running..."
+	./$(NAME) 
+
+clean:
+	-rm *o
diff --git a/x/2-4-EventDispatch/multiwindow.cpp b/x/2-4-EventDispatch/multiwindow.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..27a4fcf9824e0dc180a6effa660e6dc9c67dc7df
--- /dev/null
+++ b/x/2-4-EventDispatch/multiwindow.cpp
@@ -0,0 +1,216 @@
+/*
+CS 349 Code Examples: X Windows and XLib
+
+    dispatch     Opens and draws into two windows
+
+  					usage:
+
+  					to create sibling window:
+
+  					   ./muliwindow sib
+
+  					to create child window:
+
+  					   ./multiwindow child
+
+- - - - - - - - - - - - - - - - - - - - - -
+
+See associated makefile for compiling instructions
+
+*/
+
+#include <iostream>
+#include <list>
+#include <cstdlib>
+#include <unistd.h>
+#include <sstream>
+
+/*
+ * Header files for X functions
+ */
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+using namespace std;
+
+const int Border = 4;
+
+
+/*
+ * Information to draw on the window.
+ */
+struct XInfo {
+	Display	 *display;
+	int		 screen;
+	Window	 window;
+	GC		 gc;
+};
+
+
+
+/*
+ * Function to put out a message on error exits.
+ */
+void error( string str ) {
+	cerr << str << endl;
+	exit(0);
+}
+
+
+/*
+ * Initialize X and create a window
+ */
+void initX(int argc, char *argv[], XInfo &xinfo, Window root, 
+	int x, int y, int width, int height, string name) {
+
+	XSizeHints hints;
+	unsigned long white, black;
+
+	white = XWhitePixel( xinfo.display, xinfo.screen );
+	black = XBlackPixel( xinfo.display, xinfo.screen );
+
+	hints.x = x;
+	hints.y = y;
+	hints.width = width;
+	hints.height = height;
+	hints.flags = PPosition | PSize;
+
+	xinfo.window = XCreateSimpleWindow(
+	                   xinfo.display,				// display where window appears
+	                   root, 						// window's parent in window tree
+	                   hints.x, hints.y,			// upper left corner location
+	                   hints.width, hints.height,	// size of the window
+	                   Border,						// width of window's border
+	                   black,						// window border colour
+	                   white );					// window background colour
+
+	XSetStandardProperties(
+	    xinfo.display,		// display containing the window
+	    xinfo.window,		// window whose properties are set
+	    name.c_str(),	// window's title
+	    "",				// icon's title
+	    None,				// pixmap for the icon
+	    argv, argc,			// applications command line args
+	    &hints );			// size hints for the window
+
+	/*
+	 * Create Graphics Context
+	 */
+	xinfo.gc = XCreateGC(xinfo.display, xinfo.window, 0, 0);
+	XSetForeground(xinfo.display, xinfo.gc, BlackPixel(xinfo.display, xinfo.screen));
+	XSetBackground(xinfo.display, xinfo.gc, WhitePixel(xinfo.display, xinfo.screen));
+	XSetFillStyle(xinfo.display, xinfo.gc, FillSolid);
+	XSetLineAttributes(xinfo.display, xinfo.gc,
+	                   1, LineSolid, CapButt, JoinRound);
+
+	XSelectInput(xinfo.display, xinfo.window,
+	             ButtonPressMask | KeyPressMask | ExposureMask);
+
+	   // load a larger font
+    XFontStruct * font;
+    font = XLoadQueryFont (xinfo.display, "12x24");
+    XSetFont (xinfo.display, xinfo.gc, font->fid);
+
+	/*
+	 * Put the window on the screen.
+	 */
+	XMapRaised( xinfo.display, xinfo.window );
+
+}
+
+
+// convert to string
+string toString(int i) {
+    stringstream ss;
+    ss << i;
+    return ss.str();
+}
+
+
+
+/*
+ * Start executing here.
+ *	 First initialize window.
+ *	 Next loop responding to events.
+ *	 Exit forcing window manager to clean up - cheesy, but easy.
+ */
+int main ( int argc, char *argv[] ) {
+
+	XInfo xinfo1;
+	XInfo xinfo2;
+
+	// true: window is like heavyweight widget embedded in window
+	// false: window is just another window
+	bool isSibling = false;
+
+		/*
+	* Display opening uses the DISPLAY	environment variable.
+	* It can go wrong if DISPLAY isn't set, or you don't have permission.
+	*/
+	Display * display = XOpenDisplay( "" );
+	if ( !display )	{
+		error( "Can't open display." );
+	}
+
+	/*
+	* Find out some things about the display you're using.
+	*/
+	int screen = DefaultScreen( display );
+	xinfo1.display = display;
+	xinfo1.screen = screen;
+
+	// create window 1
+	initX(argc, argv, xinfo1, DefaultRootWindow(display), 75, 75, 200, 200, "One");
+
+	// create window 2
+	xinfo2.display = display;
+	xinfo2.screen = screen;
+
+	if (isSibling)
+		// make window 2 a sibling of window 1
+		initX(argc, argv, xinfo2, DefaultRootWindow( display ), 25, 150, 150, 50, "Two");
+	else
+		// make window 2 a child of window 1
+		initX(argc, argv, xinfo2, xinfo1.window, 25, 50, 150, 50, "Two");
+
+	XFlush(display);
+
+	// need to repaint both windows
+
+	int click1 = 0;
+	int click2 = 0;
+
+
+	XEvent event;
+
+	while ( true ) {
+		XNextEvent( display, &event );
+		switch ( event.type ) {
+		case ButtonPress:
+			if (event.xany.window == xinfo1.window) {
+				cout << "ButtonPress Window One\n";
+				click1++;
+			} else if (event.xany.window == xinfo2.window) {
+				cout << "ButtonPress Window Two\n";
+				click2++;
+			}
+			break;
+		}
+
+		// draw in the windows
+		string s;
+		s = toString(click1);
+		XDrawImageString( xinfo1.display, xinfo1.window, xinfo1.gc,
+                      25, 40, s.c_str(), s.length() );
+ 		s = toString(click2);
+		XDrawImageString( xinfo2.display, xinfo2.window, xinfo2.gc,
+                      25, 40, s.c_str(), s.length() );
+
+
+	}
+
+	/* flush all pending requests to the X server. */
+	XFlush(display);
+
+	XCloseDisplay(display);
+}