diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index b559206..3ab3a62 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -51,6 +51,8 @@ target_sources(couchlib PUBLIC
   Util.cpp
   Vertex.h
   Vertex.cpp
+  Window.h
+  Window.cpp
   World.h
   World.cpp
   Scripting/ScriptingLanguage.h
diff --git a/core/Input.cpp b/core/Input.cpp
index b1de7d8..e84b21b 100644
--- a/core/Input.cpp
+++ b/core/Input.cpp
@@ -13,19 +13,20 @@ Input *Input::GetInstance() {
   return instance;
 }
 
-void Input::Use(Window *window){
-  glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
-  glfwSetKeyCallback(window, (GLFWkeyfun)HandleKeys);
-  glfwSetCursorPosCallback(window, (GLFWcursorposfun)HandleMousePosition);
+
+void Input::Use(Window window){
+  glfwSetInputMode(window.glfwWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
+  glfwSetKeyCallback(window.glfwWindow, (GLFWkeyfun)HandleKeys);
+  glfwSetCursorPosCallback(window.glfwWindow, (GLFWcursorposfun)HandleMousePosition);
 }
 
-void Input::HandleKeys(Window *window, int keys, int code, int action, int mods) {
+void Input::HandleKeys(GLFWwindow *_, int keys, int code, int action, int mods) {
   for (KeyHandler keyHandler : instance->keyHandlers) {
-    keyHandler(window, keys, code, action, mods);
+    keyHandler(keys, code, action, mods);
   }
 }
 
-void Input::HandleMousePosition(Window *window, double xpos, double ypos) {
+void Input::HandleMousePosition(GLFWwindow *_, double xpos, double ypos) {
   double relx, rely;
   if (instance->firstMousePositionUpdate) {
     relx = 0.0;
@@ -36,7 +37,7 @@ void Input::HandleMousePosition(Window *window, double xpos, double ypos) {
     rely = ypos - instance->lasty;
   }
   for (MousePositionHandler mousePositionHandler : instance->mousePositionHandlers) {
-    mousePositionHandler(window, xpos, ypos, relx, rely);
+    mousePositionHandler(xpos, ypos, relx, rely);
   }
   instance->lastx = xpos;
   instance->lasty = ypos;
diff --git a/core/Input.h b/core/Input.h
index 9b8da02..a291068 100644
--- a/core/Input.h
+++ b/core/Input.h
@@ -6,22 +6,23 @@
 #include <vector>
 
 #include "types.h"
+#include "Window.h"
 
-typedef void (*KeyHandler)(Window *window, int key, int code, int action, int mods);
-typedef void (*MousePositionHandler)(Window *window, double xpos, double ypos, double xrel, double yrel);
+typedef void (*KeyHandler)(int key, int code, int action, int mods);
+typedef void (*MousePositionHandler)(double xpos, double ypos, double xrel, double yrel);
 
 class Input {
 public:
   static Input *GetInstance();
-  void Use(Window *window);
+  void Use(Window window);
   std::vector<KeyHandler> keyHandlers;
   std::vector<MousePositionHandler> mousePositionHandlers;
 private:
   bool firstMousePositionUpdate = true;
   double lastx, lasty;
   Input();
-  static void HandleKeys(Window *window, int key, int code, int action, int mods);
-  static void HandleMousePosition(Window *window, double xpos, double ypos);
+  static void HandleKeys(GLFWwindow *_, int key, int code, int action, int mods);
+  static void HandleMousePosition(GLFWwindow *_, double xpos, double ypos);
   static Input *instance;
 };
 
diff --git a/core/Scripting/Lua.cpp b/core/Scripting/Lua.cpp
index 73422d1..aa59654 100644
--- a/core/Scripting/Lua.cpp
+++ b/core/Scripting/Lua.cpp
@@ -83,7 +83,7 @@ bool Lua::HasHook(const char *name) {
 
 #ifdef LUA_SCRIPTING
 
-void Lua::LuaKeyHandler(Window *window, int key, int code, int action, int mods) {
+void Lua::LuaKeyHandler(int key, int code, int action, int mods) {
   lua_getglobal(L, "onkey");
   lua_pushinteger(L, key);
   lua_pushinteger(L, code);
@@ -92,8 +92,7 @@ void Lua::LuaKeyHandler(Window *window, int key, int code, int action, int mods)
   lua_call(L, 4, 0);
 }
 
-void Lua::LuaMousePositionHandler(Window *window, double xpos, double ypos, double relx, double rely) {
-  // lua_State *L = (lua_State*) glfwGetWindowUserPointer(window);
+void Lua::LuaMousePositionHandler(double xpos, double ypos, double relx, double rely) {
   lua_getglobal(L, "onmousemotion");
   lua_pushnumber(L, xpos);
   lua_pushnumber(L, ypos);
diff --git a/core/Scripting/Lua.h b/core/Scripting/Lua.h
index ce37d33..ca39d04 100644
--- a/core/Scripting/Lua.h
+++ b/core/Scripting/Lua.h
@@ -25,8 +25,8 @@ public:
 private:
 #ifdef LUA_SCRIPTING
   static lua_State *L;
-  static void LuaKeyHandler(Window *window, int key, int code, int action, int mods);
-  static void LuaMousePositionHandler(Window *window, double xpos, double ypos, double xrel, double yrel);
+  static void LuaKeyHandler(int key, int code, int action, int mods);
+  static void LuaMousePositionHandler(double xpos, double ypos, double xrel, double yrel);
   static int LuaExceptionHandler(lua_State *L1);
 #endif // LUA_SCRIPTING
 };
diff --git a/core/Window.cpp b/core/Window.cpp
new file mode 100644
index 0000000..743dafa
--- /dev/null
+++ b/core/Window.cpp
@@ -0,0 +1,43 @@
+#include "Window.h"
+
+const int width = 800;
+const int height = 600;
+
+void Window::Init() {
+  int err;
+  glfwInit();
+  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
+  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+  glfwWindowHint(GLFW_FLOATING, GLFW_TRUE);
+  glfwWindowHintString(GLFW_X11_CLASS_NAME, "Couch");
+
+  glfwWindow = glfwCreateWindow(width, height, "Couch", NULL, NULL);
+
+  if (!glfwWindow) {
+    throw "Error creating window.";
+  }
+
+  glfwMakeContextCurrent(glfwWindow);
+
+  err = glewInit();
+  if (err != GLEW_OK) {
+    throw "Error initiailizing GLEW.";
+  }
+
+  glViewport(0, 0, width, height);
+}
+
+bool Window::ShouldClose() {
+  return glfwWindowShouldClose(glfwWindow);
+}
+
+void Window::Update() {
+  glfwSwapBuffers(glfwWindow);
+  glfwPollEvents();
+}
+
+void Window::Close() {
+  glfwDestroyWindow(glfwWindow);
+  glfwTerminate();
+}
diff --git a/core/Window.h b/core/Window.h
new file mode 100644
index 0000000..7c390f8
--- /dev/null
+++ b/core/Window.h
@@ -0,0 +1,53 @@
+/**
+   @file
+   @author Dane Johnson <dane@danejohnson.org>
+ 
+   @section LICENSE
+ 
+   Couch  Copyright (C) 2021 Dane Johnson
+
+   This program comes with ABSOLUTELY NO WARRANTY; without event the
+   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+   See the GNU General Public License for details at
+   https://www.gnu.org/licenses/gpl-3.0.html
+  
+   This is free software, and you are welcome to redistribute it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3 of the License,
+   or (at your option) any later version.
+ 
+   @section DESCRIPTION
+   
+   The window controls interfacing with the operating system and creating the 
+   interface.
+*/
+#ifndef WINDOW_H
+#define WINDOW_H
+
+#include <GL/glew.h>
+#include <GLFW/glfw3.h>
+
+class Window {
+public:
+  /**
+     Initializes the window.
+   */
+  void Init();
+  /**
+     @returns whether or not the user tried to close the window
+   */
+  bool ShouldClose();
+  /**
+     Close the window.
+   */
+  /**
+     Swap the buffers and poll for events
+   */
+  void Update();
+  void Close();
+private:
+  friend class Input;
+  GLFWwindow *glfwWindow;
+};
+
+#endif /* WINDOW_H */
diff --git a/core/couch.cpp b/core/couch.cpp
index 684a181..6a63f6c 100644
--- a/core/couch.cpp
+++ b/core/couch.cpp
@@ -7,6 +7,7 @@
 #include <glm/gtc/matrix_transform.hpp>
 
 #include "types.h"
+#include "Window.h"
 
 #include "Util.h"
 
@@ -29,11 +30,6 @@
 
 #include "Scripting/Lua.h"
 
-Window *window;
-
-const int width = 800;
-const int height = 600;
-
 Node *root;
 
 void render(Node *curr, Shader *shader, Matrix model) {
@@ -59,31 +55,9 @@ void render(Node *curr, Shader *shader, Matrix model) {
 }
 
 int main() {
-
-  int err;
-  glfwInit();
-  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
-  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
-  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-  glfwWindowHint(GLFW_FLOATING, GLFW_TRUE);
-  glfwWindowHintString(GLFW_X11_CLASS_NAME, "Couch");
-
-  window = glfwCreateWindow(width, height, "Couch", NULL, NULL);
-
-  if (!window) {
-    std::cerr << "Error creating window" << std::endl;
-    return 1;
-  }
-
-  glfwMakeContextCurrent(window);
-
-  err = glewInit();
-  if (err != GLEW_OK) {
-    std::cerr << "Error initializing glew" << std::endl;
-  }
-
-  glViewport(0, 0, width, height);
-
+  Window window;
+  window.Init();
+  
   root = Node::GetRoot();
 
   Input *input = Input::GetInstance();
@@ -109,7 +83,7 @@ int main() {
   double lastTime = glfwGetTime();
   double delta = 0.0;
 
-  while(!glfwWindowShouldClose(window)) {
+  while(!window.ShouldClose()) {
     // Physics update()
     world->Step(delta);
     
@@ -164,11 +138,11 @@ int main() {
     // // Render the screen
     screenShader->Use();
     screenShader->UpdateTex(screen.tex);
-    glViewport(0, 0, width, height);
+    // Ummm?
+    // glViewport(0, 0, width, height);
     screen.Draw();
-    
-    glfwSwapBuffers(window);
-    glfwPollEvents();
+
+    window.Update();
 
     double curTime = glfwGetTime();
     delta = curTime - lastTime;
@@ -181,7 +155,6 @@ int main() {
   lua->Close();
   delete lua;
   
-  glfwDestroyWindow(window);
-  glfwTerminate();
+  window.Close();
   return 0;
 }
diff --git a/core/types.h b/core/types.h
index f25ee96..d5533e2 100644
--- a/core/types.h
+++ b/core/types.h
@@ -8,7 +8,6 @@
 #include <GLFW/glfw3.h>
 #include <glm/glm.hpp>
 
-typedef GLFWwindow Window;
 typedef glm::vec3 Vector3;
 typedef glm::mat4 Matrix;
 typedef std::string Name;