diff --git a/java/2-3-widgets/WidgetDemo.java b/java/2-3-widgets/WidgetDemo.java
new file mode 100644
index 0000000000000000000000000000000000000000..32a516cffa321dd011adb25bf65ce38c0dd9996f
--- /dev/null
+++ b/java/2-3-widgets/WidgetDemo.java
@@ -0,0 +1,115 @@
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+public class WidgetDemo {
+
+	public static void main(String[] args) {
+		WidgetDemo demo = new WidgetDemo();
+	}
+	
+	JLabel label;
+	
+	WidgetDemo()
+	{
+		JFrame f = new JFrame("WidgetDemo.java");
+		f.setSize(500, 200);
+		f.addWindowListener(new WindowAdapter() {
+			public void windowClosing(WindowEvent e) {
+				System.exit(0);
+			}
+		});
+
+		// create a button and add a listener for events
+		JButton button = new JButton("My Button");
+		button.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				label.setText("button");
+			}
+		});
+		
+		// create a slider
+		JSlider slider = new JSlider(0, 100, 50);
+		slider.addChangeListener(new ChangeListener() {
+			public void stateChanged(ChangeEvent e) {
+				JSlider s = (JSlider)e.getSource();
+				label.setText("slider " + s.getValue());
+			}
+		});
+		
+		// create a radio button group
+		ButtonGroup radiobuttons = new ButtonGroup();
+		JPanel radioPanel = new JPanel(new GridLayout(1, 0));
+		for (String s: new String[] {"A", "B", "C"})
+		{
+			JRadioButton rb = new JRadioButton(s);
+			rb.addActionListener(radioButtonListener);
+			radiobuttons.add(rb);
+			radioPanel.add(rb);
+		}
+		
+		// create a menu
+		JMenu menu = new JMenu("Choices");		
+		// create some menu choices
+		for (String s: new String[] {"apple", "orange", "banana", "pear" })
+		{
+			// add this menu item to the menu
+			JMenuItem mi = new JMenuItem(s);
+			// set the listener when events occur
+			mi.addActionListener(menuItemListener);
+			// add this menu item to the menu
+			menu.add(mi);
+		}
+		JMenuBar menubar = new JMenuBar();
+		menubar.add(menu);
+
+		// create a label
+		// (we'll use this to display messages)
+		label = new JLabel("message");
+		// set some properties to customize how it looks
+		label.setPreferredSize(new Dimension(500, 60));
+		label.setHorizontalAlignment( SwingConstants.CENTER );
+		label.setBackground(Color.WHITE);
+		label.setBorder(BorderFactory.createLineBorder(Color.black));
+		label.setFont(new Font("SansSerif", Font.PLAIN, 30));
+		
+		
+		// define the layout
+		// http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
+
+		
+		// add the widgets
+		f.add(button);
+		f.add(slider);
+		f.add(menubar);
+		f.add(radioPanel);
+		f.add(label);
+
+		f.setLayout(new FlowLayout());
+				
+		f.setVisible(true);
+	}
+	
+	// create a menu item listener
+	MenuItemListener menuItemListener = new MenuItemListener();
+	
+	class MenuItemListener implements ActionListener {
+		public void actionPerformed(ActionEvent e) {
+			JMenuItem mi = (JMenuItem)e.getSource();
+			label.setText(mi.getText());
+		}
+	}
+	
+	// create a radio button listener
+	RadioButtonListener radioButtonListener = new RadioButtonListener();
+
+	class RadioButtonListener implements ActionListener {
+		public void actionPerformed(ActionEvent e) {
+			JRadioButton rb = (JRadioButton)e.getSource();
+			label.setText(rb.getText());
+		}
+	}
+	
+}
diff --git a/java/2-3-widgets/makefile b/java/2-3-widgets/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..dcea5ae9efc87a545872d413dc3fba0f2c6dd814
--- /dev/null
+++ b/java/2-3-widgets/makefile
@@ -0,0 +1,15 @@
+# super simple makefile
+# call it using 'make NAME=name_of_code_file_without_extension'
+# (assumes a .java extension)
+NAME = "WidgetDemo"
+
+all:
+	@echo "Compiling..."
+	javac $(NAME).java
+
+run: all
+	@echo "Running..."
+	java $(NAME)
+
+clean:
+	rm -rf *.class
diff --git a/x/2-3-widgets/button.cpp b/x/2-3-widgets/button.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5962e72fb015ba9bcbf3dd717da94a6185c11dbd
--- /dev/null
+++ b/x/2-3-widgets/button.cpp
@@ -0,0 +1,257 @@
+/*
+CS 349 Code Examples: X Windows and XLib
+
+    button.cpp   Implement a ToggleButton UI Widget
+
+- - - - - - - - - - - - - - - - - - - - - -
+
+See associated makefile for compiling instructions
+
+*/
+
+#include <cstdlib>
+
+#include <unistd.h>
+#include <sys/time.h>
+#include <math.h>
+
+#include <iostream>
+#include <sstream>
+#include <list>
+#include <vector>
+
+#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;
+
+
+// - - - X globals - - -
+
+struct XInfo {
+	Display* display;
+	Window window;
+	int screen;
+	GC gc;
+};
+
+XInfo xinfo;
+
+// frames per second to run animation loop
+int FPS = 60;
+
+// helper function to set X foreground colour
+enum Colour {BLACK, WHITE};
+void setForeground(Colour c) {
+	if (c == BLACK) {
+		XSetForeground(xinfo.display, xinfo.gc, BlackPixel(xinfo.display, xinfo.screen));
+	} else {
+		XSetForeground(xinfo.display, xinfo.gc, WhitePixel(xinfo.display, xinfo.screen));
+	}
+}
+
+
+// isPaused functionality
+bool isPaused = false;
+// isPaused callback (a simple event handler)
+void togglePause(bool isOn) {
+	isPaused = isOn;
+}
+
+// A toggle button widget
+class ToggleButton {
+
+public:
+
+	ToggleButton(int _x, int _y, void (*_toggleEvent)(bool)) {
+		x = _x;
+		y = _y;
+		toggleEvent = _toggleEvent;
+		isOn = false;
+		diameter = 50;
+	}
+
+	// the CONTROLLER
+	void mouseClick(int mx, int my) {
+		float dist = sqrt(pow(mx - x, 2) + pow(my - y, 2));
+		if (dist < diameter / 2) {
+			toggle();
+		}
+	}
+
+	// the VIEW
+	void draw() {
+
+		if (isOn) {
+			setForeground(BLACK);
+			XFillArc(xinfo.display, xinfo.window, xinfo.gc,
+			         x - diameter / 2,
+			         y - diameter / 2,
+			         diameter, diameter,
+			         0, 360 * 64);
+			setForeground(WHITE);
+			XDrawArc(xinfo.display, xinfo.window, xinfo.gc,
+			         x - diameter / 2,
+			         y - diameter / 2,
+			         diameter, diameter,
+			         0, 360 * 64);
+		} else {
+			setForeground(WHITE);
+			XFillArc(xinfo.display, xinfo.window, xinfo.gc,
+			         x - diameter / 2,
+			         y - diameter / 2,
+			         diameter, diameter,
+			         0, 360 * 64);
+			setForeground(BLACK);
+			XDrawArc(xinfo.display, xinfo.window, xinfo.gc,
+			         x - diameter / 2,
+			         y - diameter / 2,
+			         diameter, diameter,
+			         0, 360 * 64);
+		}
+	}
+
+private:
+
+	// VIEW "essential geometry"
+	int x;
+	int y;
+	int diameter;
+
+	// toggle event callback
+	void (*toggleEvent)(bool);
+
+	// the MODEL
+	bool isOn;
+
+	void toggle() {
+		isOn = !isOn;
+		toggleEvent(isOn);
+	}
+};
+
+
+int main( int argc, char *argv[] ) {
+
+	xinfo.display = XOpenDisplay("");
+	if (xinfo.display == NULL) exit (-1);
+	int screennum = DefaultScreen(xinfo.display);
+	long background = WhitePixel(xinfo.display, screennum);
+	long foreground = BlackPixel(xinfo.display, screennum);
+	xinfo.window = XCreateSimpleWindow(xinfo.display, DefaultRootWindow(xinfo.display),
+	                                   10, 10, 300, 200, 2, foreground, background);
+	XSelectInput(xinfo.display, xinfo.window,
+	             ButtonPressMask | KeyPressMask); // select events
+	XMapRaised(xinfo.display, xinfo.window);
+	XFlush(xinfo.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
+	xinfo.gc = XCreateGC(xinfo.display, xinfo.window, 0, 0);
+
+	// time of last xinfo.window paint
+	unsigned long lastRepaint = 0;
+
+	XWindowAttributes w;
+	XGetWindowAttributes(xinfo.display, xinfo.window, &w);
+
+	ToggleButton toggleButton(150, 100, &togglePause);
+
+	// 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(xinfo.display) > 0) {
+			XNextEvent( xinfo.display, &event );
+
+			switch ( event.type ) {
+
+			// mouse button press
+			case ButtonPress:
+				// cout << "ButtonPress" << endl;
+				toggleButton.mouseClick(event.xbutton.x, event.xbutton.y);
+				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(xinfo.display);
+					exit(0);
+				}
+				break;
+			}
+		}
+
+		unsigned long end = now();
+
+		if (end - lastRepaint > 1000000 / FPS) {
+
+
+			// clear background
+			XClearWindow(xinfo.display, xinfo.window);
+
+			// draw ball from centre
+			setForeground(BLACK);
+			XFillArc(xinfo.display, xinfo.window, xinfo.gc,
+			         ballPos.x - ballSize / 2,
+			         ballPos.y - ballSize / 2,
+			         ballSize, ballSize,
+			         0, 360 * 64);
+
+
+			if (!isPaused) {
+
+				// 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;
+
+			}
+
+			toggleButton.draw();
+
+			XFlush( xinfo.display );
+
+			lastRepaint = now(); // remember when the paint happened
+		}
+
+		// IMPORTANT: sleep for a bit to let other processes work
+		if (XPending(xinfo.display) == 0) {
+			usleep(1000000 / FPS - (end - lastRepaint));
+		}
+
+
+	}
+	XCloseDisplay(xinfo.display);
+}
diff --git a/x/2-3-widgets/makefile b/x/2-3-widgets/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..f100361d1b1ace3ad7e1bcd2e896fb19bc4eac7d
--- /dev/null
+++ b/x/2-3-widgets/makefile
@@ -0,0 +1,19 @@
+# super simple makefile
+# call it using 'make NAME=name_of_code_file_without_extension'
+# (assumes a .cpp extension)
+NAME = "button"
+
+# 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